Androidのダイアログでユーザーの反応を待っています

何かを発明する前に、私はもちろんグーグル (彼の決定をレイアウトした後、この投稿の著者)。

実際、UIスレッドで待機することはできず、Activityはダイアログを操作するためのイベント駆動型モデルを提供します。ダイアログが閉じられると、ダイアログ識別子を持つ共通ハンドラーが呼び出されます。 このアプローチはあまり便利ではないように思えたので、すべてを自分のやり方でやることに決めました。

UIスレッドを待機させることができない場合は、別のスレッドを作成して待機させます。待機させる場合は、スレッド同期メカニズムが必要です。 この目的のために、基本的なミューテックスを作成しました。 lock()メソッドは、unlock()が呼び出されるまで制御を返しません。

public class Mutex { public synchronized void lock() throws InterruptedException { this.wait(); } public synchronized void unlock() { this.notify(); } }
      
      





次に、ダイアログを操作するためのクラスを作成し、その中にミューテックスを含めました。 クラスはダイアログを初期化し、ダイアログの完了後のユーザーの反応を保存します。 実装の重要な部分のみに焦点を合わせるために、一部のクラスメソッドの実装を省略しました。

すべてのボタンにはハンドラー(1)が割り当てられており、戻り値を変数に保存してからダイアログを閉じます。 ダイアログを閉じるハンドラー(2)は、mutexを解放します。 インターフェイス関数(3)は、ミューテックスのリリースを待機します。

 public class SyncDialog { private Dialog mDialog; private Mutex mMutex; private int mResult; private Button mYesButton; private Button mNoButton; private Button mCancelButton; public SyncDialog(Context context) { mMutex = new Mutex(); mDialog = new Dialog(context); mDialog.setContentView(R.layout.dialog); findViews(); mYesButton.setOnClickListener(new OnClickListener() { // (1) public void onClick(View v) { mResult = YES_RESULT; mDialog.dismiss(); } }); mNoButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { mResult = NO_RESULT; mDialog.dismiss(); } }); mCancelButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { mResult = CANCEL_RESULT; mDialog.cancel(); } }); mDialog.setOnDismissListener(new OnDismissListener() { // (2) public void onDismiss(DialogInterface dialog) { mMutex.unlock(); } }); } public void waitForResponse() throws InterruptedException { // (3) mMutex.lock(); } }
      
      





実際、私が最初に欲しかったのは、ユーザーの反応を待つ方法です(2)。 別のスレッドで動作するはずです。

まず、UIスレッドでSyncDialogを作成し(1)、次にバックグラウンドスレッドで初期化を送信し、ダイアログを開始して(3)UIスレッドで実行し、待機し(4)、結果を処理します(5)。

 public class MyActivity extends Activity { private SyncDialog syncDialog; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); syncDialog = new SyncDialog(this); // (1) } public void processDialogs(String... questions) { // (2) for (final String question : questions) { runOnUiThread(new Runnable() { // (3) public void run() { syncDialog.setText(question); syncDialog.show(); } }); int response; try { syncDialog.waitForResponse(); // (4) response = syncDialog.getResult(); } catch (InterruptedException e) { response = SyncDialog.CANCEL_RESULT; } if (response == SyncDialog.YES_RESULT) { // (5) Log.i(question, "Yes"); }else if (response == SyncDialog.NO_RESULT) { Log.i(question, "No"); }else break; } } }
      
      





AsyncTaskでprocessDialogs()を実行できます。

 public class DialogsTask extends AsyncTask<String, Void, Void> { @Override protected Void doInBackground(String... params) { processDialogs(params); return null; } }
      
      





イベント駆動型のアプローチを使用してダイアログを順番に表示するには、ダイアログを表示するためのデータを格納する構造のリストを作成し、ダイアログを閉じた後、リスト内の次の構造で新しいダイアログを初期化するというアイデアしかありませんでした。 この方法は私には非常に不便に思えました。 この記事がこの問題の解決策を探している人々に役立つことを願っています。



ご清聴ありがとうございました。



この例の完全なソースコードは、 ここにあります



All Articles