2012-01-18 13 views
5

並べ替えやWeb /ファイルストリームを使った作業など、さまざまな時間を費やすアクションを実行するためのアプリには、良いアプローチがありますか? このような目的で使用する方が良い:複数のAsyncTask、複数のThreadまたは1つのHandlerThreadのようなもの http://hi-android.info/src/android/webkit/WebViewWorker.java.htmlいくつかのAsyncTaskまたはHandlerThread(パイプラインスレッド)を使用する方が良いでしょうか?

+0

私の経験から、私はすべてのデータベース作業にAsyncTasksを使用します。 1つの良いことは、postExecute()に到達すると、別のスレッドが終了したことです。長い時間を要するタスク(Webからのストリーム/更新) - ハンドラまたはThreadクラスの直接拡張。 – hovanessyan

+0

私はAsyncTaskが大好きですが、Androidの一部のバージョンでは、複数のスレッドを順次ではなく並列で実行できます。これにより、データベースを操作する際に、あらゆる種類の競合が発生する可能性があります。そこに注意してください。 –

答えて

1

簡単な答えは、UIをロックしていないためです。

回答が長くなると、 が優先されます。私が使用する解決策は、基本スレッドとハンドラの組み合わせです。基本的なスレッドはメインのUIスレッド上では実行されないので、多くの場合、完了したら設定を報告したり更新したりする必要があります。これは、ハンドラと読みやすいキーのセットを使用するときです。したがって、私は任意のビューにアクセスし、必要に応じて変更することができます。宣言し、ビューへのグローバル参照を保持し、必要に応じて割り当て、使用し、完了したら破棄することは賢明ではありません。

private static final int SET_LOADING = 0; 
private static final int SET_TEXT  = 1; 


private Handler mEventHandler = new Handler() { 

    @Override 
    public void handleMessage(Message msg) { 
     // if stmts||switch - personal preference 
     if(msg.what  == SET_LOADING){ 

      setLoading(((Boolean) msg.obj)); 

     }else if(msg.what == SET_TEXT){ 

      setText(msg.arg1, (String) msg.obj); 

     } 
     super.handleMessage(msg); 
    } 
} 

/** 
* set the text of a textbox 
* @param id int - R.id.{...} 
* @param text String 
*/ 
private void setText(int id, String text){ 
    TextView t = ((TextView) findViewById(id)); 
    if(t != null){ 
     t.setText(text); 
    } 
} 


/** 
* is the UI currently loading something? lock controls 
* @param isLoading boolean 
*/ 
private void setLoading(boolean isLoading){ 
    mIsLoading = isLoading; 
    if(isLoading){ 
     (SomeSpinningProgressBar).setVisibility(View.VISIBLE); 
    }else{ 
     (SomeSpinningProgressBar).setVisibility(View.INVISIBLE); 
    } 
} 



public void onClick(View v) { 
    /** 
    * some button that triggers a database connection 
    */ 
    if(v.getId() == R.id.some_button) { 

     /** basic thread */ 
     new Thread(new Runnable() { 
       public void run() { 
        if(this.hasWebConnection()){ 
         /** tell the UI thread to start loading */ 
         mEventHandler.sendMessage(
          mEventHandler.obtainMessage(SET_LOADING, 0, 0, true)); 

         // do work... 

         if(someErrorOccuredBoolean){ 
          /** report to user of an error */ 
          mEventHandler.sendMessage(
           mEventHandler.obtainMessage(SET_TEXT, R.id.some_textview, 0, "There was an error!")); 
         } 
         /** tell the UI thread to stop loading */ 
         mEventHandler.sendMessage(
           mEventHandler.obtainMessage(SET_LOADING, 0, 0, false)); 
        }else{ 
         mEventHandler.obtainMessage(SET_TEXT, R.id.some_textview, 0, "No internet found!!")); 
        } 
       } 
      } 
     );  
    } 
} 
0

特に、ネイティブライブラリを使用する場合は、ライブラリの初期化に使用したのと同じスレッドで関数を呼び出す必要があります。その理由は、ライブラリがスレッドローカルストレージに何かを格納する可能性があるからです。この場合、AsyncTaskはオプションではありません。

システムライブラリがスレッドローカルストレージを使用するかどうか、また今後使用するかどうか... ...私の主張が分かります:安全な側にする、JNIライブラリを使用するときは1つのスレッドだけを使用することをお勧めします。これは、いいえAsyncTaskを意味します。

ところで、パイプラインスレッド(ハンドラスレッドとも呼ばれる)は一度に1つのタスクを実行するため、並列に実行される可能性のあるタスクに対して異なるハンドラスレッドを使用する必要があります。

1

は、である必要があります。何らかのタイプのワーカースレッドに対して、時間がかかる操作(ネットワーク、データベースアクセスなど)を委任する必要があります。メイン(UI)スレッドをブロックすることはできません。

AsyncTaskはハイレベルオブジェクトです。これは、内部のHandlerExecutorを使用して、スレッド処理とスレッド間通信を処理します。バックグラウンドで何かを行い、その結果をUIにプッシュする(非常に)一般的なケースのために設計されています。 HandlerHandlerThread(またはイベントThread)を使用して

は直接、より複雑なコードのコスト、およびいくつかの微妙な落とし穴(例えばHow to Leak a Context: Handlers & Inner Classes)で、あなたに多くの柔軟性を提供します。

あなたが選択したのは、タスクをシリアルまたはパラレルで実行することです。 HandlerThreadはそれらをシリアル化します。 AsyncTaskの場合、Androidのバージョンによって異なります(ただし、これは上書きすることができます)。 Threadを毎回作成すると、並列スレッドの数が過剰になる可能性があります。

関連する問題