null Canvas in SurfaceView-Thread, trotz stoppe Thread in SurfaceDestroyed () - nur auf Android 4 / ICS

8

Ich habe eine SurfaceView-Erweiterung, in der die nackten Knochen wie in Lunar Lander Beispiel. Das heißt, die Methode run() der Zeichnung Thread ist im Wesentlichen:

%Vor%

Und das Thread wird ordnungsgemäß gestoppt, wenn die Oberfläche zerstört wird:

%Vor%

Auf Geräten, die ich bisher getestet habe (HTC Desire, Desire HD und Archos 101, zwischen denen OS 2.2 und 2.3.3 sind, wenn ich mich recht erinnere), gab es nie ein Problem mit dem Obigen. Das heißt, wenn die Oberfläche zerstört wird, weil der Benutzer Activity zurücknimmt oder ein weiterer Activity oben aufgerufen wird, stellt der Code innerhalb von surfaceDestroyed() immer sicher, dass mSurfaceHolder.lockCanvas() niemals aufgerufen würde, um% co_de zurückzugeben %.

Der Unterschied zu meinem neuen HTC One X, auf dem Android 4 / ICS läuft, ist jedoch, dass während des Aufrufs der Methode null (dh der Code innerhalb dieser Methode noch ausgeführt wird) meine Zeichnung surfaceDestroyed() würde ein Thread canvas von null erhalten. Dies würde natürlich einen Anwendungsabsturz verursachen. Auf meinem One X passiert das jedes jedes Mal, wenn die Oberfläche zerstört wird - sei es durch Drehen des Telefons, Zurücksetzen von mSurfaceHolder.lockCanvas() usw.

Ich bin darüber verwirrt, weil ich den Eindruck hatte, dass Activity eine nicht mSurfaceHolder.lockCanvas() null zurückgeben sollte, bis Canvas tatsächlich exited ist. Ja, genau das sagt der Javadoc:

surfaceDestroyed()

Meine Lösung ist jetzt, einfach nach This is called immediately before a surface is being destroyed. After returning from this call, you should no longer try to access this surface. If you have a rendering thread that directly accesses the surface, you must ensure that thread is no longer touching the Surface before returning from this function. zu suchen. Das funktioniert gut:

%Vor%

Aber, irgendwelche Ideen, warum ich das plötzlich für Android 4 / ICS machen muss?

    
Trevor 28.04.2012, 14:23
quelle

2 Antworten

5

Um meinen Kommentar näher auszuführen, scheint es, dass es ein Bug-Ticket für diese Verhaltensänderung gibt, die Sie hier finden: Ссылка . Wenn es dich betrifft, könnte es sich lohnen, es anzustarren, nur damit es seine Wichtigkeit ein wenig erhöht!

Persönlich habe ich das selbst gesehen, nur indem ich das Beispiel mit dem Mondlandeten benutzt habe, das mit dem neuesten Android SDK geliefert wird. Ich lege es auf mein HTC Sensation XE (4.0.3) und bei einer Orientierungsänderung bekomme ich einige leere Bilder zurück, bevor die Oberfläche zerstört wird.

Die von mir verwendete Problemumgehung besteht also lediglich darin, zu überprüfen, ob die Zeichenfläche nicht null ist, bevor Sie sie an meine Aktualisierungs- und Rendermethoden übergeben.

Andy

    
Andy 12.02.2013, 09:57
quelle
0

Ich habe ein kleines Experiment gemacht. Ich setze einige Benachrichtigungsflags in surfaceDestroyed() methode wie folgt:

%Vor%

Was ich herausgefunden habe, ist die Tatsache, dass die nullPionterExceptionOccurs nach der ersten, aber vor der zweiten Flagge auftritt. Das bestmögliche Ergebnis für Ihre Frage ist, dass Sie den Canvas-Bereich sperren, wenn die alte Ansicht erreichbar ist. Sie zeichnen darauf, aber in der Zwischenzeit ändert sich der Bildschirm. Wenn die Leinwand entsperrt wird, gibt es keinen Platz mehr, um die Ergebnisse anzuzeigen - der Fehler wird verursacht.

P.S. Spielen Sie ein wenig mit Lunar Lander von Beispiel-Android-Codes und versuchen Sie, den Bildschirm zu drehen, während das Spiel funktioniert. Wenn der Fehler auftritt, schauen Sie einfach, wie die Hintergrund-Bitmap gezeichnet werden soll. Sie werden feststellen, dass sich die Bildschirmausrichtung geändert hat, aber das Programm hat versucht, eine Bitmap zu zeichnen, als ob nichts passiert.

    
Tinki 06.03.2013 12:44
quelle

Tags und Links