Android Learning Note (31): Threads: Message and runnable

Source: Internet
Author: User

The program needs the corresponding user's operation, the most to be able to within 200ms (0.2s), if more than 5 seconds no response, Activitymanager will kill the activity without prompting. However, activity may really take time to process, which tends to use the background thread-background thread. A background thread can safely interact with the UI thread, where the background thread is not able to modify the UI. I'm not quite sure how far you can "not modify the UI", for example, in the following example progress bar state modification is allowed, in complex examples may have problems, such as two background threads to deal with the same widget, there may be unpredictable circumstances, but in terms of programming, it should not be handled , the background process should avoid the handling of the UI, the UI's UI, and the processing of the rules. This is a good programming style or a programming principle.

By creating an object of the handler subclass, each acvivity requires only one handler object. The background process can communicate handler in two ways: the message and the Runnable object, which essentially puts the content in the handler queue, where the message is the placement information, can pass some parameters, handler get the information, and how the degree of judgment is handled , while Runnable is the direct way to deal with it. The queue is executed sequentially, and handler will process a message or perform a process in the next step, so that there is no confusion caused by multiple threads requiring UI processing at the same time.

The contents of these queues (whether message or runnable) can require immediate execution, delay execution for a certain time, or specify a moment to execute, and if they are placed in the queue header, represent the highest finite level and are immediately executed. These functions include: SendMessage (), Sendmessageatfrontofqueue (), Sendmessageattime (), sendmessagedelayed () and the Post (), Postatfrontofqueue (), Postattime (), Postdelay () used to add runnable to the queue.

In general, the recommendation is the Messge way, so that the design can be more flexible, and runnable in some simple and clear way to use. We will write a small example of three ways to learn. This example is a progress bar, every 1 seconds, the progress bar step 5, if the acvity stop, the progress bar is zeroed.

Android XML:

<?xml version= "1.0" encoding= "Utf-8"?>
<linearlayout .../>
<progressbar android:id= "@+id/c15_progress"
style= "Android:attr/progressbarstylehorizontal" <!--This shows how a traditional horizontal progress bar is used--
Android:layout_width= "Fill_parent"
android:layout_height= "Wrap_content"/>
</LinearLayout>

Example one: Thread-on, using message to pass information between the background thread and the main threads of the UI

public class Chapter15test1 extends activity{
Private ProgressBar bar = null;
Private Boolean isrunning = false;

/* We create a handler for this acivity to communicate with the daemon, simply by adding 5 to the ProgressBar progress as soon as the message is received. */
/* Step 1: Create the handler, and through Handlemessage () give the UI what to do when the message is received, an example is simply not to analyze the content of MSG */
Handler handler= New Handler () {
public voidHandlemessage(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: Set up background threading, using thread, where the contents of run () is the thread parallel processing content, thread is runnable implements*/
Thread background = new Thread (new Runnable () {
public voidRun() {
try{
for (int i = 0; i < && isrunning; i + +) {
Thread.Sleep (1000);
/* Step 2.1: Send a message to the queue, Obtainmessage () in the parameter is used to give a new message, this example has no parameters, corresponding to handler in the queue when the message is received by handlemessage () 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 we press the back key */
protected void OnStop () {
Super.onstop ();
IsRunning = false;
}
}

Example 2: Using runnable

We have modified the above example based on the following

/* Step 1: Because you do not need to process the message, you do not need to process handlemessage () */
Handler handler= new Handler ();
/* Step 1.1: Define the processing action, use the Runnable instance, implements run () to customize the processing, here is a simple step into the progress bar 5. Since we will use this instance in thread, consider using the final method */
Final Runnable r =new Runnable (){
public void Run () {
Bar.incrementprogressby (5);
}
};
/* ... ... In OnStart (), Step 2: Thread processing, and provide a message different, for runnable mode, use post */
Thread background = new Thread (new Runnable () {
public void Run () {
try{
for (int i = 0; i < && isrunning; i + +) {
Thread.Sleep (1000);
Handler.post (r);
}
}catch (Throwable t) {
Jest end the thread
}
}
});
Background.start ();

Example 3: Timed triggers can be implemented with deferred processing, making the program easier

In the example here, the fact that we are doing timed processing, using the handler queue can set the way of deferred processing, we do not need to create a background running thread, can also implement

Handler handler= new Handler ();

... ... In OnStart () ...
With handler.postdelayed (r,1000), the queue requires a delay of 1 seconds after the R processing, and in the process of R, the last in the handler queue to add a request delay 1 seconds of processing, if so, can be achieved every 1 seconds of periodic processing.
Handler.postdelayed (new Runnable (){
public void Run () {
if (isrunning && Chapter15test2.step < 20) {
Step + +;
Bar.incrementprogressby (5);
handler.postdelayed (this, +);
}
}
}, +);

In this example, we base a certain degree of judgment and automatically stop adding processing to the queue. If there is a situation, we need to clear the queue of messages or rationale, you can use Removmessages () or removecallbacks () processing, which is very useful for deferred processing, can interrupt the periodic processing. Of course, in general we want to get a certain degree of judgment so that regular processing can end gracefully, rather than simply deleting messages or processing from the queue.

Example 4: Do not know whether the main thread in the UI or the background threads

Sometimes it's not clear that the code will run on the UI thread or the background thread, for example, that the code is encapsulated as a jar, provided for other people to call, and we don't know how other people use the code. In order to solve this problem, Android provides runonuithread () in activity, and if it is in the UI thread, executes it immediately, and if it is in a background thread, adds Runnable's execution to the main thread's queue. This allows the code to execute safely, either on the UI thread or in the background thread.

We are experimenting on the basis of Example 1:

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

Runnable runaction = new Runnable () {
public void Run () {
Note that we cannot use Toast.maketext (this,....) because we cannot determine runnable specific running context
Toast.maketext (getapplicationcontext(), "hello!", Toast.length_short). Show ();
LOG.D ("WEI", "runaction .... is called");
}
};

Since the toast display and hiding takes a certain amount of time, and the interval of 1 seconds is obviously not enough, we will example 1 interval time 1000ms, instead of 5000ms this will be clearer, of course, can be used LOG.D way to replace.

2. Perform this action in the UI thread, adding the operation to the background thread, which can be performed correctly both in the UI and in the background thread.

protected void OnStart () {
... ...
Thread background = new Thread (new Runnable () {
public void Run () {
try{
for (int i = 0; i < && 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 above example, regardless of whether the background thread is used (example 1-2), the processing of handler is actually the main thread of the UI, the general use of the way we do some operations through the background thread, if we need to interact with the UI, the message or processing way to the handler queue, Handle in the main thread of the UI. This is our general situation.

Before we discussed why UI is the UI, handling of processing, however, there may be such a requirement, for example, in some cases, handler receive a message triggered by the processing may have sleep (), which causes the main thread to enter the sleep state, not what we expect. So we want to use a thread to deal with the Hanlder message, which in turn gets the information from the handler queue, processing it one after another, ensuring security without the exception thrown by the confusion.

For this Android-provided handlerthread. Ways to use the method are as follows:

Step 1: Innovate an object of the Handlerthread and open this thread, Handlerthread will process the message in handler by Looper, that is, if there is a message in handler, will be processed in this thread of handlerthread.
Handlerthread ht = new Handlerthread ("Hander_thread");
Step 2: Start Handerhandler this thread;
Ht.start ();

Step 3: Create the handler, with the Looper parameter, that is, Handlerthread.getlooper (). Note that this processing must not be called until Handlerthread is started, or an error will be returned, Getlooper () will return null, and the program has an unexpected error
Handler Handler = new Handler (Ht.getlooper ()) {
....
public void Handlemessage (Message msg) {
.../* The processing here will not be performed in the main thread, but executed in Handlerthread threads, either through Thread.CurrentThread (). GetId () or Thread.CurrentThread (). GetName () to determine */
}
};

RELATED links: My Andriod development related articles

Android Learning Note (31): Threads: Message and runnable

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.