📜 ⬆️ ⬇️

Another way to synchronize threads

This topic discusses another way to synchronize streams using Intent , BroadcastReceiver and Handler . This method may seem very cumbersome, but nevertheless quite convenient, especially if the application uses a lot of asynchronous threads. For example, if a service is being implemented that communicates with the web service in the background. Another example is an application that is ported to several platforms at once and most of the code for working with the API can be shared in Android, in J2ME, and in Windows Phone 7.


Action plan


  1. Prepare a static class with the names of intents.
  2. We create methods in the class successor Application for sending intents.
  3. From threads we send intents of events.
  4. We intercept intents in activit with the help of BroadcastReceiver .
  5. We transfer events to Handler and process them.

Intents


Intents - abstract descriptions of operations for execution (according to documentation). In the application, it is convenient to organize the storage of all constants with actions and parameters of intents in one static class. In our case, for example, we will use two actions - the list page is loaded and the picture is loaded.

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 "; … } 

Newsletter intents


Sending intents can be done through the methods of the application: available from any class, you do not need to transfer and store a link to the context.
 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)); } … } 

Therefore, the distribution of intents looks very simple:
')
 @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(); … } 

If necessary, the intent can pass additional parameters, such as the ID of the image. For this we use the putExtra method.

Interception intents


In the activation, the intents are intercepted using an anonymous instance of BroadcastReceiver . Install it at the moment of transition to the foreground and remove when the activation goes off the screen.

 /*** *       */ @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); } } }; 

The events themselves are passed to the anonymous handler, since the processing of events in the activation is most often associated with updating the components on the screen and requires execution in the UI thread. An additional advantage of this solution is that you can update components with a delay and cut off some of the events so as not to cause flickering on the screen, for example, if each list item contains a picture that is loaded in a separate thread (note the removeMessages and sendEmptyMessageDelayed methods ).

 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); } }; 


Conclusion


The method presented here looks rather cumbersome, but if you consider that in most activites it may be necessary to intercept events from threads, then it is advisable to bring this functionality to the basic activit and the rest to inherit from this base class. The code itself should be entered into Eclipse with a snippet and not entered every time.

Source: https://habr.com/ru/post/130977/


All Articles