2 votes

Pourquoi cela ne notifie-t-il pas le fil ?

Je me suis toujours demandé comment la plupart des applications créaient des dialogues de confirmation. Je sais qu'on ne peut pas bloquer le fil de l'interface utilisateur, donc j'ai quelque chose comme ça :

private synchronized boolean createDialogConfirm() {
        if(DEBUG) Log.i("Dialog", "createDialogConfirm()");
        // Creo un nuevo Thread que crea el cuadro de dialogo TODO: no funciona la confirmacion, nunca llega al return
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // Creo el dialogo con los dos botones
                AlertDialog.Builder confirm = new AlertDialog.Builder(LogicAnalizerView.this);
                confirm.setTitle("Guardar");
                confirm.setMessage("El archivo existe, sobreescribir ?");
                if(DEBUG) Log.i("Dialog", "createDialogConfirm() -> Created");

                // Boton Si
                confirm.setPositiveButton("Si", new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int whichButton) {    
                      state = true;
                      synchronized(this) { this.notifyAll(); };     // Despierta el Thread
                  }
                });

                // Boton No
                confirm.setNegativeButton("No", new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int whichButton) {
                      state = false;
                      synchronized(this) { this.notifyAll(); };
                      dialog.dismiss();   
                  }
                });
                confirm.show();
            }
        });

        if(DEBUG) Log.i("Dialog", "createDialogConfirm() - Thread created");
        try {
            synchronized(this) { wait(); }; // Queda esperando (no retorna nada) hasta que se llame a notify() en algun boton
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return state;
    }

Je l'utilise donc de cette manière à l'intérieur d'un Thread (pas un Thread d'interface utilisateur) :

if(createDialogConfirm()){ ... }

Je sais que c'est une façon peu glorieuse mais je n'en connais pas d'autre, si vous avez quelqu'un, j'aimerais bien le savoir. Le problème est que si j'appelle notifyAll() ou notify() sans synchronized(this){} j'obtiens Force Close sur mon application, mais si je l'utilise il ne revient tout simplement jamais, il semble ne jamais notifier() le Thread. L'idée est de retourner un vrai ou un faux du Thread mais seulement quand l'utilisateur a appuyé sur un bouton.

0voto

Prabuddha Points 37089

Vous pouvez utiliser Interface pour recevoir une notification/retourner une valeur de votre AlertDialog. Voir ma réponse here .

0voto

Tudor Points 39539

Je pense que votre problème vient du fait que vous synchronisez sur this qui est un objet différent lorsque vous appelez notifyAll que lorsque vous appelez wait puisque lorsque vous appelez notifyAll vous êtes à l'intérieur d'un new Runnable(...) objet. Essayez de vous synchroniser sur un objet neutre. En outre, vous devriez garder le wait avec une condition booléenne pour éviter les erreurs de synchronisation ou les réveils intempestifs :

private synchronized boolean createDialogConfirm() {

        final Object signal = new Object(); // !
        final boolean[] shouldWait = new boolean[] { true };

        if(DEBUG) Log.i("Dialog", "createDialogConfirm()");
        // Creo un nuevo Thread que crea el cuadro de dialogo TODO: no funciona la confirmacion, nunca llega al return
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // Creo el dialogo con los dos botones
                AlertDialog.Builder confirm = new AlertDialog.Builder(LogicAnalizerView.this);
                confirm.setTitle("Guardar");
                confirm.setMessage("El archivo existe, sobreescribir ?");
                if(DEBUG) Log.i("Dialog", "createDialogConfirm() -> Created");

                // Boton Si
                confirm.setPositiveButton("Si", new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int whichButton) {    
                      state = true;
                      synchronized(signal) { shouldWait[0] = false; signal.notifyAll(); }     
                  }
                });

                // Boton No
                confirm.setNegativeButton("No", new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int whichButton) {
                      state = false;
                      synchronized(signal) { shouldWait[0] = false; signal.notifyAll(); }
                      dialog.dismiss();   
                  }
                });
                confirm.show();
            }
        });

        if(DEBUG) Log.i("Dialog", "createDialogConfirm() - Thread created");
        try {
            while(shouldWait[0]) {
               synchronized(signal) { signal.wait(); }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return state;
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X