Autore Topic: AlertDialog in Thread  (Letto 1349 volte)

Offline ponticello

  • Utente junior
  • **
  • Post: 50
  • Respect: +2
    • Mostra profilo
  • Dispositivo Android:
    galaxy s2
  • Play Store ID:
    littlebridge
  • Sistema operativo:
    ubuntu 10.10
AlertDialog in Thread
« il: 19 Luglio 2012, 23:14:26 CEST »
0
BUONA SERA A TUTTI
allora ho un activity  e un view che implementa Runnable


ACTIVITY
Codice (Java): [Seleziona]
public void onBackPressed(){
               
        if(!IS_DIALOG_ON_PAUSE_VILIBLE){
                //PREMUTO BOTTONE INDIETRO DURANTE IL GIOCO
                onPause();             
        }
        else{
                //PREMUTO BOTTONE INDIETRO DURANTE LA PAUSA
                onResume();
        }
    }
   
    public void onPause(){
        super.onPause();
                       
        if(!IS_DIALOG_ON_PAUSE_VILIBLE){
                //SI VIENE DA BOTTONE INDIETRO
                game.pause();
                showDialog(DIALOG_ON_PAUSE);
                IS_DIALOG_ON_PAUSE_VILIBLE = true;
        }
    }
             
    public void onResume(){
        super.onResume();
       
        if(!IS_DIALOG_ON_PAUSE_VILIBLE){
                //SI VIENE DA PAUSA BOTTONE INDIETRO
                game.resume();
        }
        else{
                //SI VIENE DA PAUSA SPEGNIMENTO SCHERMO
                onPause();
        }
               
    }
     
    protected Dialog onCreateDialog(int id) {

        AlertDialog alertDialog = null;
        switch(id) {
                case DIALOG_ON_PAUSE:
                        AlertDialog.Builder builder;
                       
                        LayoutInflater inflater = (LayoutInflater) GameActivity.this.getSystemService(LAYOUT_INFLATER_SERVICE);
                        View layout = inflater.inflate(R.layout.dialog_on_pause,(ViewGroup) findViewById(R.id.layout_root));
                       
                        Button btnRestart = (Button) layout.findViewById(R.id.restart);
                        btnRestart.setOnClickListener(gestoreBtn);
                        Button btnResume = (Button) layout.findViewById(R.id.resume);
                        btnResume.setOnClickListener(gestoreBtn);
                        Button btnMenu = (Button) layout.findViewById(R.id.menu);
                        btnMenu.setOnClickListener(gestoreBtn);        
                       
                        builder = new AlertDialog.Builder(GameActivity.this);
                        builder.setView(layout);
                        builder.setCancelable(true);           
                        builder.setOnCancelListener(gestoreDialogCancel);
                                       
                        //Looper.prepare();
                       
                        try{
                                alertDialog = builder.create();
                        }catch(Exception e){
                                Log.i("ERRORE", "PONTE E +"+e);
                        }
                                                       
                    break;
           
        default:
                alertDialog = null;
        }
        return alertDialog;

View
Codice (Java): [Seleziona]
Thread updateThread = null;
        volatile boolean isRunning = true;
       
        public void run(){             
                while(this.isRunning){
                        this.Update(); 
                        if(gameState == GameState.GameWin){    
                                updateThread = new Thread();                           
                                ((GameActivity)getContext()).onPause();
                               
                        }
                }
        }
       
        public void resume(){
               
                this.isRunning = true;
                updateThread = new Thread(this);
                updateThread.start();
                resumeTime = System.currentTimeMillis();       
                if(pauseTime != 0){
                        starTime = starTime + (resumeTime - pauseTime);
                }
               
        }
       
        public void pause(){
               
                this.isRunning = false;
                pauseTime = System.currentTimeMillis();
                while(true){
                        try{   
                                        updateThread.join();           
                                break;
                        }catch(InterruptedException e){
                               
                        }
                }
        }

Allora premendo il tasto hardware indietro viene percepito dall'activity nel metodo onBackPressed che passa in onPause che mette in pausa il thread della view poi passa dentro onCreateDialog e crea l'alertDialog custom
Vorrei replicare la stessa cosa non appena nel metodo run della view capta che la variabile gameState è uguale a GameWin
Fin qui tutto ok ma al momento dell alertDialog = builder.create(); va in errore
Ho provato anche con Looper.prepare(); subito prima ma niente chi mi sa dare una risposta AIUTOOOOOOOOO  ???
Le mie app sullo store

    

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:AlertDialog in Thread
« Risposta #1 il: 20 Luglio 2012, 08:40:05 CEST »
+1
Puoi postare il LogCat dell'errore?
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline ponticello

  • Utente junior
  • **
  • Post: 50
  • Respect: +2
    • Mostra profilo
  • Dispositivo Android:
    galaxy s2
  • Play Store ID:
    littlebridge
  • Sistema operativo:
    ubuntu 10.10
Re:AlertDialog in Thread
« Risposta #2 il: 20 Luglio 2012, 10:57:32 CEST »
0
SENZA Looper.prepare();
Codice: [Seleziona]
07-19 20:27:00.749: ERROR/AndroidRuntime(2295): FATAL EXCEPTION: Thread-15
07-19 20:27:00.749: ERROR/AndroidRuntime(2295): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.os.Handler.<init>(Handler.java:121)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.view.ViewRoot.<init>(ViewRoot.java:242)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.view.Window$LocalWindowManager.addView(Window.java:424)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.app.Dialog.show(Dialog.java:241)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.app.Activity.showDialog(Activity.java:2566)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.app.Activity.showDialog(Activity.java:2524)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at com.valerio.memory.GameActivity.onPause(GameActivity.java:78)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at com.valerio.memory.Game.run(Game.java:719)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at java.lang.Thread.run(Thread.java:1019)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295): FATAL EXCEPTION: Thread-15
07-19 20:27:00.749: ERROR/AndroidRuntime(2295): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.os.Handler.<init>(Handler.java:121)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.view.ViewRoot.<init>(ViewRoot.java:242)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.view.Window$LocalWindowManager.addView(Window.java:424)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.app.Dialog.show(Dialog.java:241)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.app.Activity.showDialog(Activity.java:2566)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at android.app.Activity.showDialog(Activity.java:2524)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at com.valerio.memory.GameActivity.onPause(GameActivity.java:78)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at com.valerio.memory.Game.run(Game.java:719)
07-19 20:27:00.749: ERROR/AndroidRuntime(2295):     at java.lang.Thread.run(Thread.java:1019)

CON Looper.prepare(); non si genera errore ma non si genera nemmeno l'alertdialog in pratica torna nel view con thread fermo non appena tocco il pulsante hardware indetro va in creash senza stampa di errore
Le mie app sullo store

    

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:AlertDialog in Thread
« Risposta #3 il: 20 Luglio 2012, 11:36:52 CEST »
+1
Allora, vedo solo parte del codice quindi tieni conto che le mie sono supposizioni.

Il problema di fondo dovrebbe essere che tu chiami lo show() della AlertDialog da un Thread diverso da quello di UI. Per visualizzare una Dialog da un Thread, praticamente devi mandare un messaggio all'activity principale per fargliela creare. Oppure, se stai usando un AsyncTask, devi mettere quella parte di codice nelle funzioni preExecute, onProgressUpdate, postExecute, che sono automaticamente eseguite dall'UI-thread (non nella doInBackgrounds). Infine, eventualmente credo sia possibile usare anche TuaActivity.this.runOnUiThread(...) che forse nel tuo caso è la soluzione a minor impatto di codice.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline ponticello

  • Utente junior
  • **
  • Post: 50
  • Respect: +2
    • Mostra profilo
  • Dispositivo Android:
    galaxy s2
  • Play Store ID:
    littlebridge
  • Sistema operativo:
    ubuntu 10.10
Re:AlertDialog in Thread
« Risposta #4 il: 20 Luglio 2012, 15:37:28 CEST »
0
Allora cerco di spiegarmi meglio ma scusami se non uso un linguaggio puramente tecnico

Nella classe Activity setto nell onCreate una classe view fatta da me che estende View implemente Runnable
Codice (Java): [Seleziona]
 public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);    
                               
        game = new Game(this);
        setContentView(game);
    }

la view funziona bene sia la logica che il disegno...
fatta questa ho implementato una sorta di menu-pausa utilizzando un AlertDialog
Questo AlertDialog viene visualizzato quando l'Activity capta o uno spegnimento del monitor o la pressione del tasto indietro debuggando ho visto che premendo uno dei due viene richiamato direttamente il metodo delegato dentro l'Activity (es. onPause, onResume, onBackPressed) che a loro volta chiamano dei metodi dentro la view che fermano (
Codice (Java): [Seleziona]
pause(){
   thread.join()
}
o riattivano
Codice (Java): [Seleziona]
resume(){
   updateThread = new Thread(this);
   updateThread.start();
}
il thread della View
L' AlertDialog esce correttamente......

Io vorrei richiamare un AlertDialog da un "impulso" nella View ovvero se l'utente vince il livello dalla view richiamare un metodo dell'Activity per generare AlertDialog
Io ho fatto questo codice
Codice (Java): [Seleziona]
((GameActivity)getContext()).onWin();il flusso entra correttamente dentro l'activity ma se da qui gli dico di fermare il thread della view si ferma tutto come se il threadUi (CREDO) sia fermo
e se gli dico AlertDialog.show o non esce niente o mi dice che devo "not called Looper.prepare"

CONCLUSIONI FINALI
e come se premendo un pulsante hardware io entrassi a priori nel thread dell'activity e invece con il comando ((GameActivity)getContext()).onWin(); antrassi si nell'activity ma con il thread della view

Per qualsiasi cavolata abbia scritto vi chiedo perdono XD
« Ultima modifica: 20 Luglio 2012, 15:39:08 CEST da ponticello »
Le mie app sullo store

    

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:AlertDialog in Thread
« Risposta #5 il: 20 Luglio 2012, 16:24:21 CEST »
+1
Purtroppo la visione "a macchia di leopardo" del codice mi rende molto difficile comprendere come è organizzato (a dir la verità anche vedendolo tutto ci vorrebbe un po' per comprenderlo, come a tutti del resto).

Quello che ti volevo dire nel precedente post è di concentrarti su questa domanda: "quale thread cerca di creare la dialog?" Perchè una possibile causa (non dico sia questa) del tipo di errore che ricevi, è che venga chiamata da un thread dove non è ammesso.

Poi ti ho citato i messaggi perchè, in generale, le implementazioni "intrinsecamente sicure" di qualsiasi cosa abbia a che fare con elementi di UI sono quelle che usano i messaggi diretti all'Handler dell'activity.

NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline ponticello

  • Utente junior
  • **
  • Post: 50
  • Respect: +2
    • Mostra profilo
  • Dispositivo Android:
    galaxy s2
  • Play Store ID:
    littlebridge
  • Sistema operativo:
    ubuntu 10.10
Re:AlertDialog in Thread
« Risposta #6 il: 20 Luglio 2012, 17:11:37 CEST »
0
Guarda sono riuscito eseguire correttamente il codice aggiungendo questo pezzettino nella View

Codice (Java): [Seleziona]
Looper.prepare();
((GameActivity)getContext()).onWin();
Looper.loop();
Looper.myLooper().quit();

ora l'AlertDialog compare a funziona correttamente

L'ultima cosa che ti chiedo e se sai il perchè oppure se sai cosa comporta questo pezzo di codice
Grazie infinite
Le mie app sullo store