Detailed explanation of communication between child threads and UI threads in Android
1. In multi-threading programming, we often use the three classes of Handler, Thread and Runnable. So have you figured out the relationship between them? Let's explain it in detail below.
2. First of all, the principle of the single-threaded model must be followed when developing Android applications:
Android UI operations are not thread-safe and these operations must be executed in UI threads.
:
(1).Concept:
Handler is the bridge between activity and Thread/runnable. Handler runs in the main UI thread, and it and child threads can pass data through Message objects.
(2).Use:
A: Handler runs in a UI thread, mainly receives data information sent by the child thread, and uses this data to update the UI with the main thread, and is used to interact with the main thread of the UI. For example, you can use the handler to send a message, and then receive and process the message in the handler's thread.
B: The handler of the message. Through the Handler object, we can encapsulate the Message object, and then add the Message object to the MessageQueue through sendMessage(msg). When the MessageQueue loops to the Message, the handleMessage() method of the handleMessage object corresponding to the Message object will be called to process it.
C: Handler can distribute Runnable objects or Message objects.
:
Message object, as the name implies, is a class that records message information. In other words, it is the carrier of information, storing information content. There are several more important fields in this class:
(1).arg1 and arg2:We can use two fields to store the integer value we need to pass. In Service, we can use it to store the Service ID.
(2).obj:This field is of type Object, we can have this field pass an object into the recipient of the message.
(3).what:This field can be said to be a message flag, which message is received. In message processing, we can perform different processing based on different values of this field, similar to when we are processing Button events, we use switch(()) to determine which button was clicked.
Android recommends getting Message objects through () or ().This does not necessarily mean directly creating a new instance, but first checking whether there is an available Message instance from the message pool. If it exists, it will be taken out and returned to this instance. Conversely, if there is no Message instance available in the message pool, a new Message object is new according to the given parameter. By analyzing the source code, we can see that the Android system instantiates 10 Message objects in the message pool by default.
5. Source code display:
(1).activity_main.xml layout file:
<LinearLayout xmlns:andro xmlns:tools="/tools" android: android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Custom Thread inherits Thread" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Custom Runnable Implementation of Runnable" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Timely update the UI interface, Handler distributes Runnable objects" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Timely update the UI interface, Handler distributes Message objects" /> <TextView android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0" /> </LinearLayout>
(2).
package ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; public class MainActivity extends Activity implements OnClickListener { /** TAG */ private final String TAG = getClass().getSimpleName(); /** the object of the button */ private Button mButton; /** the object of the button */ private Button mButton2; /** the object of the button */ private Button mButton3; /** the object of the button */ private Button mButton4; /** the object of the TextView */ private TextView mTextView; /** Count */ private int mCount = 0; /** Logo */ private int MESSAGE_FLAG = 1; /** * How Handler distributes Runnable objects */ private Handler mHandler = new Handler(); Runnable runnable = new Runnable() { @Override public void run() { mCount++; (runnable, 1000); (mCount + ""); } }; /*** * How Handler distributes Message objects */ Handler mHandler2 = new Handler() { public void handleMessage( msg) { if ( == 1) { ("How does Handler distribute Message objects"); } } }; @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(.activity_main); initView(); } /** * Initialize component objects */ private void initView() { mButton = (Button) findViewById(); mButton2 = (Button) findViewById(.btn2); mButton3 = (Button) findViewById(.btn3); mButton4 = (Button) findViewById(.btn4); (this); (this); (this); (this); mTextView = (TextView) findViewById(); } @Override public void onClick(View v) { switch (()) { case : { // Method 1: Inheritance method: Custom Thread inherits Thread and starts a new thread new MyThread().start(); break; } case .btn2: { // Method 2: Implementation method: implement Runnable new Thread(new MyRunnable()).start(); break; } // Method 3: handler distributes Runnable objects: timely updates the UI interface and executes the scheduled tasks immediately case .btn3: { // Handler distributes Runnable objects (runnable); break; } // Method 4: Handler distributes Message objects, updates the UI interface regularly, and executes the scheduled tasks immediately case .btn4: { // This method is not recommended // Message msg = new Message(); // This method of obtaining objects is recommended: obtain available Message objects from the message pool Message msg = (); = MESSAGE_FLAG; (msg); break; } default: break; } } }
(3).
package ; import ; /*** * Customize a MyRunnable thread * * @author scd * */ public class MyRunnable implements Runnable { public MyRunnable() { super(); } /** TAG */ private final String TAG = getClass().getSimpleName(); @Override public void run() { for (int i = 0; i < 20; i++) { (TAG, ().getName() + ", the method of implementation" + i); } } }
(4)
package ; import ; /*** * Customize a thread * * @author scd * */ public class MyThread extends Thread { public MyThread() { super(); } /** TAG */ private final String TAG = getClass().getSimpleName(); @Override public void run() { (); for (int i = 0; i < 10; i++) { (TAG, ().getName() + ",Inherit the Thread class:" + i); } } }