スレッドを同期する別の方法

このトピックでは、 IntentBroadcastReceiver、およびHandlerを使用してストリームを同期する別の方法について説明します。 この方法は非常に煩雑に思えるかもしれませんが、それでも非常に便利です。特に、アプリケーションが多くの非同期スレッドを使用する場合は便利です。 たとえば、バックグラウンドでWebサービスと通信するサービスが実装されている場合。 別の例は、一度に複数のプラットフォームに移植されるアプリケーションで、ほとんどのAPI作業コードはAndroid、J2ME、およびWindows Phone 7で共有できます。





アクションプラン



  1. インテントの名前を持つ静的クラスを準備しています。

  2. インテントを送信するために、 アプリケーション後継クラスでメソッドを作成します。

  3. スレッドからイベントインテントを送信します。

  4. BroadcastReceiverを使用してアクティビティでインテントをキャッチします。

  5. イベントをハンドラーに渡し、処理します。



意図



インテントは、実行のための操作の抽象的な説明です(ドキュメントによる)。 アプリケーションでは、すべての定数のストレージをアクションとインテントパラメータで1つの静的クラスに整理すると便利です。 この例では、たとえば、2つのアクションを使用します-リストページが読み込まれ、画像が読み込まれます。



public final class Intents { //     public final static String LIST_PAGE_RECEIVED = "com.olsoft.list.page.received"; //   public final static String IMAGE_RECEIVED = "com.olsoft.image.received "; … }
      
      





ニュースレターの意図



インテントの送信は、アプリケーションメソッドを介して実行できます。どのクラスからもアクセス可能であり、コンテキストへのリンクを転送および保存する必要はありません。

 public class SampleApplication extends Application { private static SampleApplication mInstance; @Override public void onCreate() { super.onCreate(); mInstance = this; … } /*** *    */ public static SampleApplication getInstance() { return mInstance; } /*** *      * * @param action –  */ public void sendBroadcastIntent(String action) { final Intent intent = new Intent(action); sendBroadcast(intent); } /*** * ,     */ public static void notifyListPageLoaded() { getInstance().sendBroadcast(new Intent(Intents. LIST_PAGE_RECEIVED)); } /*** * ,    */ public static void notifyImageLoaded() { getInstance().sendBroadcast(new Intent(Intents.IMAGE_RECEIVED)); } … }
      
      





したがって、インテントの送信は非常に簡単に見えます。



 @Override public void OnDownloadComplete(byte[] data) { … parseData(data); SampleApplication.notifyListPageLoaded(); … } @Override public void OnDownloadComplete(byte[] data) { … mImage = BitmapFactory.decodeByteArray(data, 0, data.length); SampleApplication.notifyListPageLoaded(); … }
      
      





必要に応じて、追加のパラメーター、たとえば画像IDをインテントに転送できます。 これを行うには、 putExtraメソッドを使用します。



インテントの傍受



アクティビティでは、 BroadcastReceiverの匿名インスタンスを使用してインテントをキャプチャします。 アクティビティがフォアグラウンドに移動した瞬間にインストールし、アクティビティが画面を離れたときに削除します。



 /*** *       */ @Override protected void onResume() { super.onResume(); IntentFilter f = new IntentFilter(); f.addAction(Intents.LIST_PAGE_RECEIVED); f.addAction(Intents.IMAGE_RECEIVED); registerReceiver(mNotificationReceiver, f); … } /*** *       */ @Override protected void onPause() { unregisterReceiver(mNotificationReceiver); super.onPause(); } /*** *  .        UI  */ private BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Intents.IMAGE_RECEIVED.equalsIgnoreCase(action)) { mHandler.removeMessages(MESSAGE_IMAGE_LOADED); mHandler.sendEmptyMessageDelayed(MESSAGE_IMAGE_LOADED, 250); } else if (Intents. LIST_PAGE_RECEIVED.equalsIgnoreCase(action)) { mHandler.sendEmptyMessage(MESSAGE_NEXT_PAGE); } } };
      
      





アクティビティでのイベント処理はほとんどの場合、画面上のコンポーネントの更新に関連付けられており、UIスレッドでの実行を必要とするため、イベント自体を匿名ハンドラーに渡します。 このソリューションの追加の利点は、たとえば、各リスト項目に個別のスレッドにロードされた画像が含まれている場合に、画面をちらつかないように、コンポーネントを遅延して更新し、いくつかのイベントを遮断できることです( removeMessagesおよびsendEmptyMessageDelayedメソッドに注意してください)。



 private final static int MESSAGE_NEXT_PAGE = 1; private final static int MESSAGE_IMAGE_LOADED = 2; /** *  .  ,      UI thread */ private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_NEXT_PAGE: mAdapter.notifyDataSetChanged(); break; case MESSAGE_IMAGE_LOADED: mAdapter.notifyDataSetChanged(); break; default: break; } super.handleMessage(msg); } };
      
      







おわりに



ここに記載されているメソッドはやや面倒ですが、ほとんどのアクティビティでスレッドからイベントをインターセプトする必要がある可能性があることを考慮すると、この機能をベースアクティビティに転送し、残りをこのベースクラスから継承することをお勧めします。 コード自体はEclipseスニペットに入力する必要があり、毎回入力する必要はありません。




All Articles