Android basics 02 -- thread security 2: handler, message, and runnable

Source: Internet
Author: User

Android UI operations are not thread-safe, and only the main thread can operate the UI. At the same time, the main thread has a certain time limit on UI operations (up to 5 seconds ). To perform some time-consuming operations (such as downloading and opening large files), Android provides some column mechanisms. The articles in the "android basics 02-thread security" series refer to a series of articles compiled by many online users and introduce the main methods. They are as follows:

Android basics 02 -- thread security 1: Definitions and Examples

Android basics 02 -- thread security 2: handler, message, and runnable

Android basics 02 -- thread security 3: Message, messagequeue, handler, Logoff

Android basics 02 -- thread security 4: handlerthread

Android basics 02 -- thread security 5: asynctask

4. Message Queue implementation

As mentioned above, in Android, only the main thread can perform UI operations. In our example, an error occurs when the subthread operates the UI.

To run the program, we use the following solution:

Private edittext; private handler messagehandler; @ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); edittext = (edittext) findviewbyid (R. id. weather_city_edit); button = (button) findviewbyid (R. id. goquery); button. setonclicklistener (this); // obtain the logoff instance of the current thread. Because the current thread is a UI thread, you can also use logoff. getmainlogoff () to get logoff = logoff. mylogoff (); // you do not need to set logoff here, because handler uses the logoff messagehandler = new messagehandler (logoff) of the previous thread by default );}

@ Override public void onclick (view v) {// create a sub-thread to perform time-consuming network connection work. New thread () {@ override public void run () {// name of the city entered by the activity user string city = edittext. gettext (). tostring (); // call the Google weather API to query the weather conditions of a specified city on the day string weather = getwetherbycity (city); // create a message object, and assign the obtained weather information to the message object message = message. obtain (); message. OBJ = weather; // messagehandler that carries the weather condition is published through handler. sendmessage (Message );}}. start ();}

// Subclass A handler class messagehandler extends handler {public messagehandler (loginloader) {super (login) ;}@ override public void handlemessage (Message MSG) {// process received message and display the weather information on the title settitle (string) MSG. OBJ );}}

The preceding program is implemented by message queue. The weather forecast program after the message queue is rewritten can run successfully, because the handlemessage method of handler is actually called by the UI Thread associated with the message queue, updating the title in the UI thread does not violate the android single-thread model principle.

5. Message Queue

The message queue of Android is used in the preceding section. When talking about message queues, we can think of a process: generating a message-receiving a message (storing it in a Message Queue)-message queue-processing a message. Here, the implementation of Android involves handler, messagequeue, logoff, and other definitions. The following is a one-to-one introduction:

1. Handler

It mainly accepts data sent by sub-threads and uses this data with the master thread to update the UI.
Explanation: When an application is started, Android will first enable a main thread (that is, the UI thread). The main thread is the UI control in the management interface for event distribution. For example, if you click a button, Android will distribute the event to the button to respond to your operation. If you need a time-consuming operation, such as reading data online or reading a large local file, you cannot put these operations in the main thread, if you put it in the main thread, the interface will be suspended. If the process is not completed in five seconds, you will receive an error message "Force disable" from the Android system ". at this time, we need to put these time-consuming operations in a sub-thread. Because the sub-thread involves UI update, the main Android thread is thread insecure, that is, updating the UI can only be updated in the main thread. Operations in the Child thread are dangerous.
At this time, Handler came up to solve this complicated problem. Because handler runs in the main thread (in the UI thread), it and the sub-thread can transmit data through the message object, at this time, handler is responsible for receiving the message object (containing data) transmitted by the subthread using the sedmessage () method ), put these messages into the main thread queue and update the UI with the main thread.

Handler can distribute the message object and runnable object to the main thread. Each handler instance is bound to the thread that creates the handler (usually located in the main thread ),
It has two functions: (1) scheduling a message or runnable to execute somewhere in a main thread; (2) arranging an action to execute in different threads.

Methods for sending messages in Handler
Post (runnable)
Postattime (runnable, long)
Postdelayed (runnable long)
Sendemptymessage (INT)
Sendmessage (Message)
Sendmessageattime (message, long)
Sendmessagedelayed (message, long)
The post method above allows you to arrange a runnable object to the main thread queue,
Sendmessage class method, allows you to arrange a message object with data into the queue, waiting for updates.

1.1 message and runnable

By creating a handler subclass object, each acviver requires only one handler object. The background process can communicate with handler in two ways: the message and runnable objects. The result is essentially to put the content in the handler queue, the message is to put information, and some parameters can be passed, handler obtains the information and determines how to handle it, while runnable directly provides a method for processing. The queue is executed in sequence. Handler processes a message or executes a processing task in the next step, so that there is no confusion caused by simultaneous UI processing by multiple threads.

The content in these queues (whether message or runnable) can be executed immediately, with a certain delay or a specified time. If they are placed in the queue header, the queue has a maximum limit, run now. These functions include sendmessage (), sendmessageatfrontofqueue (), sendmessageattime (), sendmessagedelayed (), post (), postatfrontofqueue (), postattime (), postdelay ().

Generally, the messge method is recommended, so that the program design can be more flexible, while runnable is used in some simple and clear methods. We will compile a small example in three ways to learn. This example shows a progress bar. Every 1 second, the progress bar goes 5. If the acsag stops, the progress bar returns to zero.

Android XML:

<? XML version = "1.0" encoding = "UTF-8"?> <Linearlayout.../> <progressbar Android: Id = "@ + ID/c15_progress" style = "? Android: ATTR/progressbarstylehorizontal "<! -- This indicates that the traditional horizontal progress bar is used --> Android: layout_width = "fill_parent" Android: layout_height = "wrap_content"/> </linearlayout>

Example 1: When the thread is enabled, message is used to transmit information between the background thread and the UI main thread.

Public class chapter15test1 extends activity {private progressbar bar = NULL; private Boolean isrunning = false;/* we create a handler for this acivity to communicate with the background program, simply, once a message is received, the progress of progressbar is increased by 5. * // * Step 1: Create a handler and use handlemessage () to show how the UI processes the received message, in this example, the content of MSG is not analyzed. */handler = new handler () {public void handlemessage (Message MSG) {bar. incrementprogressby (5) ;}}; protected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. chapter_15_test1); bar = (progressbar) findviewbyid (R. id. c15_progress);}/* on Start is called when the UI is initialized and displayed */protected void onstart () {super. onstart (); Bar. setprogress (0);/* Step 2: Create a background thread for processing. Use a thread. The content of run () is the content processed by the thread in parallel, thread is the implements of runnable */thread background = new thread (New runnable () {public void run () {try {for (INT I = 0; I <20 & isrunning; I ++) {thread. sleep (1000);/* Step 2.1: send the message to the queue. The obtainmessage () parameter is used to provide a new message. In this example, no parameter is specified, when handlemessage is received by handler in the queue, handlemessage () is used for processing */handler. sendmessage (handler. obtainmessage () ;}} catch (throwable t) {// jest end the thread }}); isrunning = true;/* Step 3: Start the thread */background. start ();}/* onstop is called when the UI stops displaying. For example, if we press the return key */protected void onstop () {super. onstop (); isrunning = false ;}}

Example 2: Use runnable

We can make modifications based on the above example, as shown below:

/* Step 1: Because you do not need to process the message, that is, you do not need to process handlemessage () */handler = new handler ();/* Step 1.1: Define the processing action, runnable instances are customized through implements run (). Here, the progress bar is simply step 5. Because we will use this instance in thread, we should consider using the final Method */FINAL runnable r = new runnable () {public void run () {bar. incrementprogressby (5 );}};/*...... in onstart (), Step 2: thread processing is different from providing message. For runnable mode, use Post */thread background = new thread (New runnable () {public void run () {try {for (INT I = 0; I <20 & isrunning; I ++) {thread. sleep (1000); handler. post (r) ;}} catch (throwable t) {// jest end the thread }}); background. start ();

Example 3: This program can also implement scheduled triggering with latency processing to make the program simpler.

In this example, we implement scheduled processing. We can use the handler queue to set an extended processing method. We do not need to create a backend running thread or implement it.

Handler handler = new handler ();...... in onstart ()...... // use handler. postdelayed (R, 1000), requires R processing after 1 second delay in the queue, while in R processing, finally, add a Processing request with a delay of 1 second to the handler queue. If so, regular processing can be performed every 1 second. Handler. postdelayed (New runnable () {public void run () {If (isrunning & chapter15test2. step <20) {step ++; Bar. incrementprogressby (5); handler. postdelayed (this, 1000) ;}}, 1000 );

In this example, we automatically stop adding processing to the queue based on a certain degree of determination. In some cases, if we need to clear the messages or messages in the queue, we can use removmessages () or removecallbacks () for processing. This is very useful for processing latency, regular handling can be interrupted. Of course, in general, we want to get a certain degree of determination so that regular processing can end elegantly, rather than simply deleting messages or processing from the queue.

Example 4: The main UI thread or background thread is unknown.

Sometimes, we do not know whether the code will run in the UI thread or background thread. For example, the Code is encapsulated as a jar and provided to others for calling. We do not know how others use the code. To solve this problem, Android provides runonuithread () in the activity. If it is in the UI thread, it will be executed immediately. If it is in the background thread, then, the runnable execution content is added to the queue of the background thread, so that the code can be safely executed in both the UI thread and background thread.

We will conduct an experiment on the basis of Example 1:

1. Create a runnable so that we can experiment in the UI and background thread.

Runnable runaction = new runnable () {public void run () {// note that toast cannot be used. maketext (this ,....), because we cannot determine the specific context toast of runnable. maketext (getapplicationcontext (), "Hello! ", Toast. length_short). Show (); // log. D (" wei "," runaction... is called ");}};

It takes some time to display and hide toast, but the interval of 1 second is obviously not enough. We will change the interval of 1 to 1000 ms, which will be clearer. Of course, log can be used. d.

2. Execute this operation in the UI thread and add this operation to the background thread. This operation can be correctly executed either in the ui or in the background thread.

protected void onStart() {    ... ...     Thread background = new Thread(new Runnable(){        public void run() {            try{                for(int i = 0; i < 20 && isRunning; i ++){                    Thread.sleep(5000);                    handler.sendMessage(handler.obtainMessage());                     runOnUiThread (runAction);                }            }catch(Throwable t){                //jest end the thread            }         }               });            isRunning = true;    background.start();     runOnUiThread (runAction);}

Example 5: handlerthread

In the preceding example, whether or not the background thread is used (Example 1-2), handler actually processes the UI main thread, the general method is to execute some operations through the background thread. If UI interaction is required, the message or processing method is sent to the handler queue, and then processed in the UI main thread. This is a general situation.

We have previously discussed why the UI is UI-based and processing. However, there may be such a requirement. For example, in some cases, handler may have sleep () during processing when receiving a message, which leads the main thread to enter the sleep status, which is not what we expect. Therefore, we want to use a thread to process the hanlder messages. This thread also obtains information from the handler queue in sequence and processes the messages one by one to ensure security and avoid exceptions caused by chaos.

Handlerthread for Android. The method is as follows:

// Step 1: innovate an object of handlerthread and enable this thread. handlerthread processes messages in the handler pair through logoff, that is, if there is a message in the handler, it will be processed in the handlerthread thread. Handlerthread ht = new handlerthread ("hander_thread"); // Step 2: Start the thread of handerhandler; ht. start (); // Step 3: Create handler with The logoff parameter, that is, handlerthread. getlooper (). Note: This process can only be called after handlerthread is started. Otherwise, an error is reported. If getloiter () returns NULL, Handler handler = new handler (HT. getlooper ()){.... public void handlemessage (Message MSG ){...... /* The processing here will not be executed in the main thread, but in the handlerthread thread, it can be executed through thread. currentthread (). GETID () or thread. currentthread (). getname () to determine */}};

Related Article

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.