2013-08-09 16 views
58

HandlerThreadを使用する最良の使用例を理解しようとしています。定義に従ってHandlerThreadを他の類似クラスよりもベストに使用する

「ルーパーを持つ新しいスレッドを起動するための便利なクラスルーパーは、その後ハンドラクラスを作成するために使用することができる開始()がまだ呼び出さなければなりませんに注意してください。。。」

私はThreadLooperHandlerを使用することによって達成することができ、間違ったが、同様の機能かもしれません。だからいつHandlerThreadを使うべきですか?例が本当に役立つでしょう。

+0

私はHandlerThreadを使用したことがない、多分この記事が役立ちます - http://stackoverflow.com/questions/7462098/handlerthread-vs-executor -when-is-one-more-over-the-other –

+1

@TalKanel:返信ありがとうございます。私はこの記事をチェックしましたが、HandlerThread上のExecutorの利点について話しています。私の質問は、HandlerThreadを使うのに最も良いユースケースと似ています。 – Androidme

+0

その投稿もこの問題に対処しています。エグゼキュータは、スレッドのプールを管理できるという点でより柔軟性があります。複数のスレッド - Executorを使用する必要があります。シングルスレッド - HandlerThreadを使うことができます。実行者coulcが両方の状況をカバーしているので重要ではない。私が理解しているように、HandlerThreadでは、バックグラウンドスレッドでハンドラを作成することができます。これは、他の方法でも実行できるものです。 – Rarw

答えて

71

ここでは、HandlerThreadが便利な実際の生活の例です。カメラプレビューフレームに登録すると、onPreviewFrame()コールバックでそれらを受信します。 documentationは、を説明しています。このコールバックは、スレッドopen(int)がから呼び出されたイベントで呼び出されます。

通常、これはメイン(UI)スレッドでコールバックが呼び出されることを意味します。したがって、巨大なピクセル配列を処理するタスクは、メニューが開いたり、アニメーションがアニメーション化されたり、画面上に統計が表示されたりしてもスタックしないことがあります。

簡単な解決策は、(私はpost(Runnable)を通してそれをやった、あなたはHandler.Callbackを実装する必要はありません)。このスレッドにnew HandlerThread()とデリゲートCamera.open()を作成することです。

カメラでの他のすべての作業は通常どおり行うことができますが、Camera.startPreview()またはCamera.setPreviewCallback()をHandlerThreadに委任する必要はありません。安全な側になるためには、は、Camera.open(int)が完了するまで待ってからを待ってから、メインスレッド(または変更前にCamera.open()を呼び出すために使用されたスレッド)を続行します。


だから、あなたはコードで始まる場合

try { 
    mCamera = Camera.open(1); 
} 
catch (RuntimeException e) { 
    Log.e(LOG_TAG, "failed to open front camera"); 
} 
// some code that uses mCamera immediately 

最初の抽出物には、プライベートメソッドにあるよう

private void oldOpenCamera() { 
    try { 
     mCamera = Camera.open(1); 
    } 
    catch (RuntimeException e) { 
     Log.e(LOG_TAG, "failed to open front camera"); 
    } 
} 

との代わりに、単にnewOpencamera()を使用oldOpenCamera()を呼び出します:

private void newOpenCamera() { 
    if (mThread == null) { 
     mThread = new CameraHandlerThread(); 
    } 

    synchronized (mThread) { 
     mThread.openCamera(); 
    } 
} 
private CameraHandlerThread mThread = null; 
private static class CameraHandlerThread extends HandlerThread { 
    Handler mHandler = null; 

    CameraHandlerThread() { 
     super("CameraHandlerThread"); 
     start(); 
     mHandler = new Handler(getLooper()); 
    } 

    synchronized void notifyCameraOpened() { 
     notify(); 
    } 

    void openCamera() { 
     mHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       oldOpenCamera(); 
       notifyCameraOpened(); 
      } 
     }); 
     try { 
      wait(); 
     } 
     catch (InterruptedException e) { 
      Log.w(LOG_TAG, "wait was interrupted"); 
     } 
    } 
} 

注全体を通知することを() - あなたはそれを開いた後、すぐに元のコードにmCameraにアクセスしない場合待ち()スレッド間通信は必要ありません。

更新:がここに同じアプローチが加速度計に適用されます:Acclerometer Sensor in Separate Thread

+4

どこでカメラを閉じますか? – Matthias

+2

@Matthias:それは良い質問です。あなたのユースケースでこれが許されている場合は、まずActivity.onPause()でカメラを解放します。これは、あなたのアクティビティがシステムから受け取ることが保証された_onlyコールバックであるため、[Activity lifecycle](http: //developer.android.com/reference/android/app/Activity.html#ActivityLifecycle)。しかし、カメラ_after_onPause()を使用できる場合があります。このような場合、さまざまなシナリオでは優雅になるために必要な場所はほとんどありません。 –

+1

)}}新しいRunnableを閉じる}} – Rich

14

ここにHandlerThreadLooperのソースコードへのリンクです。

HandlerThreadは正確にはで始まり、Looperという便利な方法であることがわかります。なぜこれが存在するのでしょうか? threads, by default do not have a message loopです。 HandlerThreadは、作成する簡単な方法です。ソースコードから判断するとHandlerThreadLooperとこの機能を複製できますか?回答はyesです。

Executorが異なります。 Executorは提出された実行可能なタスクをとり、それらを実行するものを推測します。なぜこれが必要ですか?それはdecouple the execution of the task from its actual substanceにすることができます。あなたはいつこれを使用しますか?同時に複数のタスクを実行する必要がある状況があったとします。 Executorを使用して、それらをすべて1つのスレッド上で実行して、連続して実行できるようにすることができます。または、固定スレッドプールを使用して、すべてが同時に実行されないようにすることもできます。どちらの場合でも、タスクの内容、つまり実際に何を実行しているかは、実行されている方法とは別です。

+1

私はあなたの区別が不正確だと思います。 Handler.postRunnableを介して実行するタスクを送信することもできます。実際には、ThreadFactoryとsubmit()メソッドを変更するだけで、HandlerThreadsだけを使用するExecutorServiceを作成できます。 HandlerThreadsではタスクが送信されずに簡単になるのは、スレッド間通信です。 – Delyan

+1

私は不明だったと思います。私は、Executorでタスクの実行が容易であることを示唆することを意味しませんでした。むしろ、Executorの目的はそれらのタスクの実行のみを処理するように設計されています。 HandlerThreadは異なる目的を果たします。私は後でそれを編集します。 – Rarw

関連する問題