6

私の小さなアプリでは、システムから一連のキューに入れられたonEventXXX()を受け取ります(私は制御していません)。

これらのonEventXXX()のタイミングは保証されていません。保証される唯一のことは、それらがキューに入れられた順序で受け取られることです。

onEventXXX()内で、別のプロセス(P)が進行している間は開始できない操作(O)を実行する必要があります。

しかし、私はこの「操作の実行(O)」を単に破棄することはできません。そのプロセス(P)が完了するまで待ってから、それを起動する必要があります

IOW、そのプロセス(P)が完了するまで、「操作の実行」をキューに入れるか、少なくとも延期する必要があります。

これを実装するための私の当面のアイデアは、操作(O)を実行する代わりに、次のようにすることでした。

  1. プロセス(P)を定期的にチェックするワンショットタイマーを開始します
  2. タイマーが経過したときに、プロセス(P)が完了していない場合は、時間(それ自体)を再開します。
  3. タイマーが経過し、プロセス(P)が完了すると、操作(O)が実行されます。

しかし、Androidの豊富さを知っているので、これを行うためのより良い方法があり、すでにシステム/APIに組み込まれているのではないかと思います。

上記を実装するためのより良い方法がある場合、それは何でしょうか?

4

3 に答える 3

3

私はそれをこのようにします:

  • onEventXで、プロセスが終了したかどうかを確認します。終了した場合は、すぐにアクションを実行します(このステップを省略して、2番目のステップを実行することもできます)

  • それ以外の場合は、doInBackgroundでProcess.waitfor()を呼び出すAsyncTaskを作成し、完了したら、onPostExecuteでアクションを実行します。

このアプローチでは、UIスレッドで、できるだけ早くアクションを呼び出します。

このタスクにはタイマーを使用しないでください。タイマーは「ポーリング」方式です。タイマーの刻みが速すぎると、CPU時間を無駄にするだけです。カチカチ音が遅すぎる場合は、アクションが遅れて呼び出される可能性があります。

于 2012-04-02T06:33:57.990 に答える
3

CountDownLatchが最適なソリューションです。

詳細な例はありませんが、簡単に使えると思います。

プロセスは以下のようになります

  1. CountDownLatch変数の名前付きラッチを定義する
  2. ラッチカウントを1に設定します
  3. イベントOを受信したら、新しいThreadOを作成します。ThreadOで、ラッチのカウントが0に達するまで待ちます。
  4. プロセスPが完了すると、カウントダウンラッチ。

そのようにコーディングすれば、多くの状況を簡単に処理できます。

  1. Oが最初に受信された場合は、Pが完了するまで待つことができます。
  2. Pが最初に受信された場合は、すぐにOを開始できます。
  3. CountDownLatchが提供するタイムアウト機能を使用できます。

asycユニットテストでCountDownLatchを使用します。あなたはここで私のコードを見ることができます:http://kingori.egloos.com/4554640

あなたの場合とは異なりますが、私のコードからヒントを得ることができます。また、CountDownLatchのjavadocが良い例です。

于 2012-04-06T05:45:21.103 に答える
2

まず、ユーザーが何かをクリックした場合、すぐに結果が表示されるはずです。あなたの場合、ボタンアクションが何かを待つ必要がある場合は、ボタンにサークル読み込みアニメーションを追加して、アクションが発生することをユーザーに通知します。まもなく。

アクション自体については、1つ(または少数)の可能なバックグラウンドプロセスの後に発生する可能性のあるアクションが1つ(または少数)しかない場合、ボタンに同期的にフラグを立てさせ(おそらく永続的なクラスメンバーを介して)、長いプロセスは、プロセスの終了後にそのフラグを同期的にチェックし、終了時に要求されたアクションを実行します。

待機と通知を使用してボタンコードにプロセスの終了を待機させる場合の別の可能なオプション。これは通常、Javaの非常に高性能なソリューションと見なされます。

たとえば(タイプミスは無視してください。これはその場で行われます):

button.setOnClickListener(new OnClickListener() { 
    public void onClick(View v) {
        v.post(new Runnable() {
            @Override
            public void run() {
                synchronized (lockObject) {
                    try {
                        lockObject.wait();
                        doAction();
                    } catch (InterruptedException e) {}
                }
            }
        }
    }
}

notifyその後、終了時に長いプロセスを実行します。

new Runnable()新しいスレッドを作成するのではなく、単にスレッドキューRunnableにを追加することに注意してください。View

マウスが示唆しているように、ボタンonClickハンドラーは、プロセスが現在実行されていないかどうかを確認する必要があります。実行されている場合は、すぐにアクションを実行します。

このようにして、新しいスレッド(または実際にはスレッドのプールであるAsyncTask)を作成する必要はありません。

于 2012-04-05T08:40:41.030 に答える