2

ほとんどのアプリケーションが確認ダイアログをどのように作成するのか、私はいつも疑問に思っていました。UIスレッドをブロックできないことはわかっているので、次のようなものがあります。

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;
    }

したがって、スレッド内でこのように使用します(UIスレッドではありません):

if(createDialogConfirm()){ ... }

私はそれが醜い方法であることを知っていますが、他の方法を知りません. 問題は、notifyAll() または notify() を Synchronized(this){} なしで呼び出すと、アプリで Force Close が発生することですが、それを使用すると、単に返されないため、Thread を notify() しないように見えます。アイデアは、ユーザーが何らかのボタンを押した場合にのみ、スレッドから true または false を返すことです。

4

2 に答える 2

0

InterfaceAlertDialogから通知を受け取ったり、値を返したりするために使用できます。私の答えを確認してくださいhere

于 2012-07-03T04:52:16.560 に答える
0

あなたの問題は、あなたが呼び出したときとは異なるオブジェクトである に同期しているという事実から来ているとthis思います. ニュートラル オブジェクトで同期を試みます。さらに、タイミングの競合や偽のウェイクアップを防ぐために、ブール条件で をガードする必要があります。notifyAllwaitnotifyAllnew Runnable(...)wait

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;
    }
于 2012-07-03T09:30:24.140 に答える