Android logoff, handler, message, and messagequeue

Source: Internet
Author: User

I,Overview

Communication between Android threads is actually a very important issue, so we must have a clear understanding of it. The question is not complete. We should add thread and runnable. Next we will introduce them separately.

II,Introduction

1. Message

A message defines a message that contains a description and any data object and can be sent to a handler. This object contains two additional int fields and one additional object field. This class has several important fields:
A. arg1 and arg2: We can use two fields to store the integer values we need to pass.
B. OBJ: this field is of the object type. We can use this field to transmit multiple entries to the receiver of the message.
C. what: this field can be said to be a message identifier. In message processing, we can perform different processing based on different values of this field, similar to when we are processing a button event, switch (v. GETID () determines which button is clicked.

When using message, we can create a message instance through new message (). However, for Android, we recommend that you use message. Obtain () or handler. obtainmessage () to obtain the message object. This is not necessarily to create a new instance directly, but to check whether there is any available message instance from the message pool. If there is a message instance, the instance is taken out and returned. If no message instance is available in the message pool, a new message object is created based on the specified parameter. By analyzing the source code, we can know that the Android system instantiates 10 message objects in the message pool by default.

2. messagequeue

A message queue is used to store the data structure of a message object and store messages according to the "first-in-first-out" principle. Storage does not actually mean saving, but concatenates message objects in a linked list. The messagequeue object does not need to be created by ourselves, but is managed by a loose object. A thread can have at most one messagequeue. We can use logoff. myqueue () to obtain the messagequeue in the current thread.

3. Logoff

Logoff is a tool used to add a messagequeue to a thread and wait cyclically. When there is a message, it will arouse the thread to process the message until the thread ends. Normally, logoff is not used, because for system components such as activity and service, frameworks has initialized the thread (commonly known as the UI thread or main thread) for us and contains a logoff, and the message queue created by logoff, so the main thread will continue to run and process user events until some events (back) Exit. Messagequeue manager, in a thread, if there is a loose object, there must be a messagequeue object, and only one loose object and one messagequeue object. In the Android system, except for the main thread, there is a default logoff object. By default, other threads do not have logoff objects. If we want the newly created thread to have a logoff object, we should first call The logoff. Prepare () method, and then call the logoff. Loop () method.

If we need to create a new thread, and this thread needs to be able to process the message events sent by other threads cyclically, or to perform complex interaction with other threads for a long time, in this case, logoff is required to establish a message queue for the thread.

Logoff is also very simple, and there are few methods, the most important of which are four:
Public static prepare ();
Public static mylogoff ();
Public static loop ();
Public void quit ();
The usage is as follows:
1. Call lorule. Prepare () in the run () method of each thread to initialize the message queue for the thread.
2. Call lorule. mylorule () to obtain the reference of this lorule object. This is not necessary, but if you need to save the logoff object, it must be after prepare (). Otherwise, the method called on this object may not be effective, such as logoff. quit () won't quit.
3. Add handler in the run () method to process messages.
4. Add logoff. Loop () call to start the thread's message queue and receive messages.
5. When you want to exit the message loop, call logoff. Quit (). Note that this method is called on the object. Obviously, the object means to exit the specific logoff. If no other operation is performed in run (), the thread stops running.

The API is described in this way. Most of the interactions with a message loop are implemented through handler. The official website provides a typical example, as shown below:

 

  class LooperThread extends Thread {      public Handler mHandler;      public void run() {          Looper.prepare();          mHandler = new Handler() {              public void handleMessage(Message msg) {                  // process incoming messages here              }          };          Looper.loop();      }  }

Here is an example:

 

 

public class LooperDemoActivity extends Activity {    private WorkerThread mWorkerThread;    private TextView mStatusLine;    private Handler mMainHandler;       @Override    public void onCreate(Bundle icicle) {       super.onCreate(icicle);       setContentView(R.layout.looper_demo_activity);       mMainHandler = new Handler() {     @Override     public void handleMessage(Message msg) {       String text = (String) msg.obj;         if (TextUtils.isEmpty(text)) {          return;  }        mStatusLine.setText(text);     } }; mWorkerThread = new WorkerThread(); final Button action = (Button) findViewById(R.id.looper_demo_action); action.setOnClickListener(new View.OnClickListener() {     public void onClick(View v) {  mWorkerThread.executeTask("please do me a favor");     } }); final Button end = (Button) findViewById(R.id.looper_demo_quit); end.setOnClickListener(new View.OnClickListener() {     public void onClick(View v) {  mWorkerThread.exit();     } }); mStatusLine = (TextView) findViewById(R.id.looper_demo_displayer); mStatusLine.setText("Press 'do me a favor' to execute a task, press 'end of service' to stop looper thread");    }       @Override    public void onDestroy() { super.onDestroy(); mWorkerThread.exit(); mWorkerThread = null;    }       private class WorkerThread extends Thread {      protected static final String TAG = "WorkerThread";      private Handler mHandler;      private Looper mLooper; public WorkerThread() {     start(); } public void run() {     // Attention: if you obtain looper before Looper#prepare(), you can still use the looper     // to process message even after you call Looper#quit(), which means the looper does not     //really quit.     Looper.prepare();     // So we should call Looper#myLooper() after Looper#prepare(). Anyway, we should put all stuff between Looper#prepare()     // and Looper#loop().     // In this case, you will receive "Handler{4051e4a0} sending message to a Handler on a dead thread     // 05-09 08:37:52.118: W/MessageQueue(436): java.lang.RuntimeException: Handler{4051e4a0} sending message     // to a Handler on a dead thread", when try to send a message to a looper which Looper#quit() had called,     // because the thread attaching the Looper and Handler dies once Looper#quit() gets called.     mLooper = Looper.myLooper();     // either new Handler() and new Handler(mLooper) will work     mHandler = new Handler(mLooper) {  @Override  public void handleMessage(Message msg) {      /*       * Attention: object Message is not reusable, you must obtain a new one for each time you want to use it.       * Otherwise you got "android.util.AndroidRuntimeException: { what=1000 when=-15ms obj=it is my please       * to serve you, please be patient to wait!........ } This message is already in use."       *///      Message newMsg = Message.obtain();      StringBuilder sb = new StringBuilder();      sb.append("it is my please to serve you, please be patient to wait!\n");      Log.e(TAG, "workerthread, it is my please to serve you, please be patient to wait!");      for (int i = 1; i < 100; i++) {   sb.append(".");   Message newMsg = Message.obtain();   newMsg.obj = sb.toString();   mMainHandler.sendMessage(newMsg);   Log.e(TAG, "workthread, working" + sb.toString());   SystemClock.sleep(100);      }      Log.e(TAG, "workerthread, your work is done.");      sb.append("\nyour work is done");      Message newMsg = Message.obtain();      newMsg.obj = sb.toString();      mMainHandler.sendMessage(newMsg);  }     };     Looper.loop(); } public void exit() {     if (mLooper != null) {  mLooper.quit();  mLooper = null;     } } // This method returns immediately, it just push an Message into Thread's MessageQueue. // You can also call this method continuously, the task will be executed one by one in the // order of which they are pushed into MessageQueue(they are called). public void executeTask(String text) {     if (mLooper == null || mHandler == null) {  Message msg = Message.obtain();  msg.obj = "Sorry man, it is out of service";  mMainHandler.sendMessage(msg);  return;     }     Message msg = Message.obtain();     msg.obj = text;     mHandler.sendMessage(msg); }    }}

In this example, when a task is executed in the main thread only sends a message to the service thread and transmits the relevant data, the data is packaged into a message object ), then put it in the message queue of the service thread, and the call of the main thread returns, this process is very fast, so it will not block the main thread. Every time a message enters the message queue, the service thread is awakened to retrieve the message from the queue and then execute the task. The service thread can receive any number of tasks, that is, the main thread can continuously send messages to the service thread, these messages will be put into the message queue, the service thread executes them one by one until all tasks are completed (the message queue is empty and no other messages exist ), the service thread enters the sleep state again until a new message arrives.
If you want to terminate the service thread and call quit () on the mlooper object, the message loop is exited. Because the thread has no other operations, the whole thread is terminated. It should be noted that when the message loop of a thread has exited, messages cannot be sent to it. Otherwise, an exception will throw "runtimeexception: handler {4051e4a0} sending message to a handler on a dead thread ". Therefore, we recommend that you. after prepare (), call logoff. mylogoff () is used to obtain the reference to this logoff. First, it is used to terminate (quit () must be called on the object ); in addition, it is used to check whether the message cycle has exited when receiving messages (for example, above ).

 

4. Handler

A handler allows you to send and process a message and runnable object associated with the messagequeue of a thread. Each handler instance is associated with a single thread and the mesagequeue of this thread. When you create a new handler instance, it is bound to the thread/Message Queue thread that creates it. Since then, it will process the messages and runnables in the messagequeue, execute the message from messagequeue. It is the processor of a message. Through the handler object, we can encapsulate the message object, and then add the message object to messagequeue through sendmessage (MSG); When messagequeue loops to this message, the handlemessage () method of the handler object corresponding to the message object will be called to process it. Because the handlemessage () method processes messages, we should write a class that inherits from handler and then process the required operations in handlemessage.

Handler has two main functions: 1. Plan messages and runnables to be executed at a certain time in the future. 2. Put an action to be executed by other threads into the queue. Handler plays the role of adding and processing messages to MQ (only processing messages sent by itself), that is, notifying MQ that it wants to execute a task (sendmessage ), and execute the handlemessage when the loop is reached. The whole process is asynchronous. Handler is associated with a logoff when it is created. The default constructor will be associated with the Logoff of the current thread, but this can also be set. the main thread of Android is also a logoff thread (logoff is widely used in Android). The Handler we create in it will be associated with the main thread MQ by default. Therefore, a solution using handler is to create a handler in the activity and pass its reference to the worker thread. After the worker thread completes the task, it sends a message to notify the activity to update the UI. (Process ).


import android.os.Message;public class SonThread extends Thread { private int i = 0; @Override public void run() {  while (i < 100) {   i = i + 10;   Message msg = new Message();   msg.arg1 = i;   try {    Thread.sleep(1000);   } catch (InterruptedException e) {    e.printStackTrace();   }   HandlerTestActivity.myHandler.sendMessage(msg);  }  if (i == 100) {   HandlerTestActivity.myHandler.removeCallbacks(this);  } }}import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.widget.ProgressBar;public class HandlerTestActivity extends Activity { private ProgressBar progressBar; private SonThread myThread; public static Handler myHandler; public void init() {  progressBar = (ProgressBar) findViewById(R.id.progressBar1);  myThread = new SonThread();  myThread.start();  myHandler = new Handler() {   @Override   public void handleMessage(Message msg) {    super.handleMessage(msg);    progressBar.setProgress(msg.arg1);   }  }; } @Override public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.main);  init(); }}

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.