Ho un'estensione SurfaceView in cui sono implementate le sue strutture come nell'esempio Lunar Lander. Cioè, il metodo del disegno Thread
run()
è essenzialmente:null Canvas in SurfaceView Thread, nonostante l'arresto Thread in surfaceDestroyed() - solo su Android 4/ICS
public void run() {
while (mRun) {
Canvas c;
try {
c = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder) {
doDraw(c); // Main drawing method - not included in this code snippet
}
}
finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
E la Thread
venga chiusa correttamente quando la superficie è distrutto:
public void surfaceDestroyed(SurfaceHolder holder) {
// we have to tell thread to shut down & wait for it to finish, or else
// it might touch the Surface after we return and explode
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
retry = false;
}
catch (InterruptedException e) {
}
}
}
Sui dispositivi solito ho testato a data (HTC Desiderio, Desiderio HD e Archos 101 che tra loro hanno OS 2.2 e 2.3.3 se ricordo bene) non c'è mai stato un problema con quanto sopra. Cioè, quando la superficie viene distrutta perché l'utente esce dal Activity
o un altro Activity
viene invocato in cima, il codice all'interno di surfaceDestroyed()
assicura sempre che mSurfaceHolder.lockCanvas()
non venga mai chiamato perché restituisca null
.
La differenza che ho trovato sul mio nuovo HTC One X su cui è in esecuzione Android 4/ICS, tuttavia, è che durante la chiamata al metodo surfaceDestroyed()
(ovvero il codice all'interno di tale metodo è ancora in esecuzione) verrà fornito il mio disegno Thread
una tela null
da mSurfaceHolder.lockCanvas()
. Ciò ovviamente causerebbe un arresto anomalo dell'applicazione. Sul mio One X, questo accadrà ogni singola volta la superficie è distrutta - sia che si tratti a causa ruotando il telefono, retromarcia dal Activity
, ecc
Sono confuso su questo perché ero sotto la impressione che mSurfaceHolder.lockCanvas()
dovrebbe restituire un numero non null
Canvas
fino al surfaceDestroyed()
ha effettivamente terminato. In effetti, questo è quello che dice il Javadoc:
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.
La mia soluzione per ora è quello di verificare solo per null
. Funziona bene:
if(c != null){
doDraw(c); // Main drawing method - not included in this code snippet
}
Ma, qualche idea per cui dovrei improvvisamente farlo per Android 4/ICS?
Restituire "null" è un modo per evitare di toccare anche la superficie, quindi quello che si dovrebbe fare va bene. Idk perché o cosa è cambiato nell'implementazione sottostante. – zapl
Grazie, zapl. Sì, è davvero bizzarro. A meno che non ci sia qualcosa di strano che sto facendo per causare questo apparente cambiamento nell'implementazione, sicuramente molte applicazioni basate su SurfaceView moriranno su ICS. – Trevor
Qualcuno trova un "ufficiale" perché perché ho ricevuto questo errore anche su dispositivi o emulatori ICS. – Lenciel