Autore Topic: Activity/Thread pause,resume con dialog  (Letto 1828 volte)

Offline thebestneo

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
Activity/Thread pause,resume con dialog
« il: 06 Marzo 2012, 15:58:07 CET »
0
Ciao a tutti,
ho un problema nel mio gioco (labirinto con pallina).

Io ho un'activity "maze" che crea una surfaceview:
Codice (Java): [Seleziona]
public class RendererView extends SurfaceView  implements SurfaceHolder.Callback, Runnable, SensorEventListener{}Quando il giocatore raggiunge la buca, chiamo un metodo nell'activity che crea un alertDialog:

Codice (Java): [Seleziona]
public void onWin(){
         AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this);
                        alertBuilder.setMessage("Hai vinto!\n Vuoi fare un'altra partita?").setCancelable(false).setPositiveButton("Si", new DialogInterface.OnClickListener() {
                               
                                public void onClick(DialogInterface dialog, int which) {
                                        dialog.dismiss();
                                Log.d("debug","Alert dismissed");
                                        rv.resume();
                                        Log.d("debug","Click Yes");
                                }
                        }).setNegativeButton("No", new DialogInterface.OnClickListener() {
                               
                                public void onClick(DialogInterface dialog, int which) {
                                        Log.d("debug","Click No");
                                        dialog.dismiss();
                                        Log.d("debug","Alert dismissed");
                                        finish();
                                }
                        });
                        Log.d("debug","Show dialog");
                        alertBuilder.show();
    }

Il comportamento che vorrei ottenere è:
-Pressione "si": riprende il thread con un nuovo labirinto
-Pressione "no": termina thread e activity e torna all'activity precedente

Partendo dal secondo caso, che dovrebbe essere più semplice, non ho ben capito lo stato in cui va l'activity alla comparsa di un dialog. Va in stato "pause"? Facendo delle stampe non sembra, però in giro ho notato che dovrebbe andarci. In quel caso volevo mettere in pausa anche il thread, in attesa della risposta dell'utente.

La mia run() del thread:
Codice (Java): [Seleziona]
public void run() {
                Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
        startTime = System.nanoTime();
            while (running) {
                if(GAME_PAUSED){
                        /*try {
                                        Thread.sleep(100);
                                } catch (InterruptedException e) {
                                        e.printStackTrace();
                                }*/

                        Log.d("debug", "Game Paused");
                }
                else{
                    try {
                        System.out.println("Running...");
                        currTime = System.nanoTime();
                        deltaTime =  (System.nanoTime() - startTime) / 1000000000.0f;
                        startTime = currTime;
                        c = holder.lockCanvas();
                        drawMaze(c);
                    }
                    finally {
                        if (c != null) {
                            holder.unlockCanvasAndPost(c);
                        }
                    }
                }
            }
            Log.d("debug","Dying");
        }
Ma non basta settare
Codice (Java): [Seleziona]
GAME_PAUSED=true;
Se premo il tasto "back" tutto funziona correttamente, ma nel caso di risposta al dialog mi si blocca tutto.
Grazie!


Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Activity/Thread pause,resume con dialog
« Risposta #1 il: 06 Marzo 2012, 16:45:57 CET »
0
Probabilmente il problema che hai (non ho ben chiaro cosa è di preciso che non ti funziona) è dovuto a questo: contrariamente a quanto potrebbe sembrare normale, in Android le dialog NON sono modali (per scelta deliberata dei progettisti). Non hanno quindi nessun effetto di blocco.

Se ti occorre ad esempio un comportamento simile a quello di una dialog modale, occorre prevedere esplicitamente una qualche  sincronizzazione. Cioè prima di far comparire la dialog blocchi tutto quello che deve essere bloccato; poi nella dialog poco prima di chiuderla con dismiss, mandi un messaggio all'activity per dirgli cosa dovrà fare.

Ci sono un altro paio di trucchi da usare come approccio alternativo: (1) usare una activity secondaria con sfondo trasparente al posto della dialog, ecco che riesci a mandare in pausa la tua activity primaria; (2) creare la dialog direttamente nel layout dell'activity con tanto di testo e button, però metterla normalmente invisibile, quando vuoi mostrarla la rendi visibile.

Spero quanto meno di averti dato qualche spunto.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline thebestneo

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
Re:Activity/Thread pause,resume con dialog
« Risposta #2 il: 06 Marzo 2012, 18:13:06 CET »
0
Probabilmente il problema che hai (non ho ben chiaro cosa è di preciso che non ti funziona) è dovuto a questo: contrariamente a quanto potrebbe sembrare normale, in Android le dialog NON sono modali (per scelta deliberata dei progettisti). Non hanno quindi nessun effetto di blocco.

Se ti occorre ad esempio un comportamento simile a quello di una dialog modale, occorre prevedere esplicitamente una qualche  sincronizzazione. Cioè prima di far comparire la dialog blocchi tutto quello che deve essere bloccato; poi nella dialog poco prima di chiuderla con dismiss, mandi un messaggio all'activity per dirgli cosa dovrà fare.

Ci sono un altro paio di trucchi da usare come approccio alternativo: (1) usare una activity secondaria con sfondo trasparente al posto della dialog, ecco che riesci a mandare in pausa la tua activity primaria; (2) creare la dialog direttamente nel layout dell'activity con tanto di testo e button, però metterla normalmente invisibile, quando vuoi mostrarla la rendi visibile.

Spero quanto meno di averti dato qualche spunto.

Sicuramente si, intanto mi premeva sapere la questione delle dialog modali/non modali, perchè da qualche parte avevo visto che, avendo le dialog il focus, mandavano in pausa l'activity, mentre da quello che dici continuano la loro attività.

Intanto grazie.

Il mio problema è che alla pressione dei tasti del dialog il thread si blocca.
Quando appare la dialog vorrei metterlo in pausa, poichè se l'utente risponde "si" il thread deve ripartire, mentre se l'utente risponde "no" l'intera activity deve finire.

Come termino nel secondo caso il thread? Mi sembra di aver letto che uscendo dal loop della run() il thread termini, mentre ho visto che alcuni usano la funzione "join()".

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Activity/Thread pause,resume con dialog
« Risposta #3 il: 06 Marzo 2012, 18:50:19 CET »
0
Come termino nel secondo caso il thread? Mi sembra di aver letto che uscendo dal loop della run() il thread termini, mentre ho visto che alcuni usano la funzione "join()".

Uscito della run il thread termina. La join() ti serve se in un altro thread vuoi essere sicuro che il thread sia effettivamente terminato, ad esempio prima di avviarne uno nuovo.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline thebestneo

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
Re:Activity/Thread pause,resume con dialog
« Risposta #4 il: 06 Marzo 2012, 19:34:23 CET »
0
Uscito della run il thread termina. La join() ti serve se in un altro thread vuoi essere sicuro che il thread sia effettivamente terminato, ad esempio prima di avviarne uno nuovo.

Ok, non ho ben capito però come usare join().
Io ho il thread dell'activity e ne creo un altro per gestire la surfaceview. In molti esempi ho visto che per terminare il thread della surfaceview viene usato proprio join().

Un'altra cosa, il dialog da dove è meglio chiamarlo, nell'activity o nella surfaceview?

Nella surfaceview in ogni caso mi richiedeva questo codice:
Codice (Java): [Seleziona]
Looper.prepare();
((DisiMaze)context).onWin();
Looper.loop();
Looper.myLooper().quit();
O in alternativa un handler. Va bene questo codice?
« Ultima modifica: 06 Marzo 2012, 19:37:27 CET da thebestneo »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Activity/Thread pause,resume con dialog
« Risposta #5 il: 06 Marzo 2012, 20:24:39 CET »
0
Ok, non ho ben capito però come usare join().
Io ho il thread dell'activity e ne creo un altro per gestire la surfaceview. In molti esempi ho visto che per terminare il thread della surfaceview viene usato proprio join().

No aspetta, join non serve a terminare il thread. Traduci join con "aspetto finchè non termina".

Nella tua SurfaceView avrai idealmente una funzione come questa per terminare il thread: non appena invoca mette isrunning a false. Isrunning sarà una variabile membro della classe thread che fa ciclare il thread fintanto che è true. Passando a false al prossimo giro il thread lascerà la run(), tu per aspettare che ci arrivi usi join.

Codice (Java): [Seleziona]
    public void stopThread ()
    {
        mThread.isrunning = false;
        try
        {
            mThread.join();
        }
        catch (InterruptedException e)
        {
            Log.e("STOPTHREAD", "error in stopThread");
        }      
    }

Su dove mettere la Dialog non saprei, ma a istinto preferirei nell'activity.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline thebestneo

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
Re:Activity/Thread pause,resume con dialog
« Risposta #6 il: 06 Marzo 2012, 20:32:59 CET »
0
No aspetta, join non serve a terminare il thread. Traduci join con "aspetto finchè non termina".

Nella tua SurfaceView avrai idealmente una funzione come questa per terminare il thread: non appena invoca mette isrunning a false. Isrunning sarà una variabile membro della classe thread che fa ciclare il thread fintanto che è true. Passando a false al prossimo giro il thread lascerà la run(), tu per aspettare che ci arrivi usi join.

Codice (Java): [Seleziona]
    public void stopThread ()
    {
        mThread.isrunning = false;
        try
        {
            mThread.join();
        }
        catch (InterruptedException e)
        {
            Log.e("STOPTHREAD", "error in stopThread");
        }      
    }

Su dove mettere la Dialog non saprei, ma a istinto preferirei nell'activity.

Perchè devo aspettare che ci arrivi? Ci sono condizioni in cui può non arrivare a finire la run()??

Per il dialog quindi va bene come ho fatto, a chiamare una funzione nell'activity... Il looper è usato correttamente?

Grazie.

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Activity/Thread pause,resume con dialog
« Risposta #7 il: 06 Marzo 2012, 20:57:24 CET »
0
Perchè devo aspettare che ci arrivi? Ci sono condizioni in cui può non arrivare a finire la run()??

Beh la run finisce, ma non sai quando. Metti che ricrei un thread prima che quello prima sia terminato, possono esserci situazioni in cui questo genera un crash dell'app. In ogni caso male non fa.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline thebestneo

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
Re:Activity/Thread pause,resume con dialog
« Risposta #8 il: 06 Marzo 2012, 22:46:37 CET »
0
Uhm ok.
Se il resto mi dici che è abbastanza corretto provo a rivedere qualcosa.

Intanto grazie.

Offline thebestneo

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
Re:Activity/Thread pause,resume con dialog
« Risposta #9 il: 07 Marzo 2012, 10:26:26 CET »
0
Niente continua a bloccarsi.

L'alert comunque mi blocca in qualche modo il thread anche se non capisco come, non viene chiamato nessun metodo per metterlo in pausa.

Comunque, questo è il codice del listener sul pulsante "No":
Codice (Java): [Seleziona]
public void onClick(DialogInterface dialog, int which) {
                                        Log.d("debug","Click No");
                                        dialog.dismiss();
                                        Log.d("debug","Alert dismissed");
                                        rv.stop();
                                        finish();
                                }

dove rv.stop() è definito cosi:
Codice (Java): [Seleziona]
public void stop() {
                Log.d("debug", "Thread stop");
                running = false;
                boolean retry = true;
        while (retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
                Log.d("Exception", e.toString());
            }
        }
        }

Il logcat:
Codice: [Seleziona]
03-07 10:21:55.453: D/debug(770): Win!
03-07 10:21:55.453: D/debug(770): Show dialog
03-07 10:21:57.803: D/debug(770): Click No
03-07 10:21:57.803: D/debug(770): Alert dismissed
03-07 10:21:57.803: D/debug(770): Thread stop
03-07 10:22:32.493: D/debug(770): Activity paused
03-07 10:22:32.493: D/debug(770): Thread paused
In qualche modo il thread rimane incastrato, perchè dopo un secondo l'activity va in pausa...

Offline thebestneo

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
Re:Activity/Thread pause,resume con dialog
« Risposta #10 il: 09 Marzo 2012, 13:55:08 CET »
0
Ho risolto. Chiamando onWin in mezzo alle chiamate del looper e chiudendo l'activity nel mentre in pratica non mi chiudeva il looper.

Quindi un consiglio:
usate SEMPRE gli handler per gestire i messaggi tra il thread e l'activity!!!