Android Source Series < seven > in-depth understanding of intentservice and Handlerthread from the source point of view

Source: Internet
Author: User
Tags call back

Reprint Please specify source: http://blog.csdn.net/llew2011/article/details/51373243

The service is familiar to everyone, and it is one of the Android Four (SI) Large (DA) group (jing) pieces (gang). But speaking of Intentservice have child boots may be a little strange, look at the name feel and service-related connection. Good, not only has the association and the relationship is not general, Intentservice is the service subclass, so it is also the authentic service, because intentservice with the help of Handlerthread, Today we are from the source of the angle of the intentservice and Handlerthread to see where they are sacred, if you are very familiar with them, please skip this article (*^__^*) ...

Before we begin the Intentservice source code, let's look at its basic usage, since Intentservice is an authentic service, and its usage is the same as service. Intentservice is also an abstract class that needs to implement its abstract method Onhandleintent (). We first define the Backgroundservice, make it inherit intentservice and implement its abstract method Onhandleintent (), then rewrite the Intentservice life cycle method and print the log with the following code:

public class Backgroundservice extends Intentservice {private static final String TAG = BackgroundService.class.getSimple Name ();p ublic Backgroundservice () {Super ("TT"); LOG.E (TAG, "Backgroundservice ()" + Thread.CurrentThread ());} @Overridepublic void OnCreate () {LOG.E (TAG, "onCreate ()" + Thread.CurrentThread ()); Super.oncreate (); @Overridepublic void OnStart (Intent Intent, int startid) {log.e (TAG, "OnStart ()" + Thread.CurrentThread ()); s Uper.onstart (Intent, Startid);} @Overridepublic int Onstartcommand (Intent Intent, int flags, int startid) {log.e (TAG, "Onstartcommand ()" + THREAD.C Urrentthread ()); return Super.onstartcommand (Intent, flags, Startid);} @Overridepublic void OnDestroy () {LOG.E (TAG, "OnDestroy ()" + Thread.CurrentThread ()); Super.ondestroy (); @Overridepublic ibinder onbind (Intent Intent) {log.e (TAG, "onbind ()" + Thread.CurrentThread ()); return super . Onbind (intent);} @Overrideprotected void Onhandleintent (Intent Intent) {LOG.E (TAG, "onhandleintent ()" + Thread.CurrentThread ());}} 
        We added a log in the overridden part of the method, primarily printing the current method name and the name of the thread where the method was executed. Then configure Backgroundservice in the configuration file Manifest.xml, with the following code:
<manifest xmlns:android= "http://schemas.android.com/apk/res/android" package= " Com.llew.wb.source.intentservice "android:versioncode=" 1 "android:versionname=" 1.0 "> <uses-sdk android:min        sdkversion= "8"/> <application android:allowbackup= "true" android:icon= "@drawable/ic_launcher" Android:label= "@string/app_name" android:theme= "@style/apptheme" > <activity Android:nam                E= "com.llew.wb.source.MainActivity" android:label= "@string/app_name" > <intent-filter> <action android:name= "Android.intent.action.MAIN"/> <category android:name= "android.in Tent.category.LAUNCHER "/> </intent-filter> </activity> <service android:name=" Com.llew.wb.source.BackgroundService "> </service> </application></manifest>
Finally, add a button to the mainactivity layout file Activity_layout.xml, which is used to start the backgroundservice. The layout file code is as follows:
<?xml version= "1.0" encoding= "Utf-8"? ><framelayout xmlns:android= "http://schemas.android.com/apk/res/ Android "    android:layout_width=" match_parent "    android:layout_height=" match_parent ">    <button        android:layout_width= "wrap_content"        android:layout_height= "wrap_content"        android:layout_gravity= " Center "        android:onclick=" StartService "        android:text=" Test Intentservice "/></framelayout>

After you have defined the layout file, add the Startintentservice () method to the mainactivity in the following code:

public class Mainactivity extends Activity {@Overrideprotected void onCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main);} public void StartService (view view) {Intent action = new Intent (this, backgroundservice.class); StartService (action);}}
OK, everything is ready, let's run a look at the print results. Run the program with the output as shown:

Depending on the print results, you can determine that the Intentservice life cycle function Execution order is oncreate () →onstartcommon () →onstart () →onhandleintent () →ondestroy (). Again, the thread information that is printed finds that only onhandleintent () thread information is different from the thread information of other functions, that is, the thread where Onhandleintent () resides and other functions are not the same thread, and we know that the other functions are executed in the main thread. So the execution of Onhandleintent () is performed in a sub-thread. There is also a little OnDestroy () method that executes after the execution of the Onhandleintent () method, because we do not actively invoke the method that stops the service, So it is possible to guess that the operation that makes the Intentservice stop must be in the same thread as the Onhandleintent () method.

Based on speculation, we continue to experiment, since the Onhandleintent () method is executed in a sub-thread, then we can use the thread hibernation to simulate the background more time-consuming operation, modify the Onhandleintent () method, the code is as follows:

@Overrideprotected void Onhandleintent (Intent Intent) {log.e (TAG, "onhandleintent ()       " + thread.currentthread ()); try {thread.sleep (3000); LOG.E (TAG, "Sleep finish           " + Thread.CurrentThread ())} catch (Exception e) {e.printstacktrace ();}}
In the Onhandleintent () method, let the thread on which it resides sleeps for 3 seconds, and then run the program with the following output:

According to the output, in the Onhandleintent () method first printed the first sentence of log, wait 3 seconds after the second sentence to print out the log content, log after printing is executed service OnDestroy () method. We continue to do the implementation, just just in the Onhandleintent () method simulation did a time-consuming task, and now we start multiple intentservice, each start with a parameter to represent each task, continue to modify the StartService () method , the code is as follows:

public void StartService (view view) {Intent action1 = new Intent (this, backgroundservice.class); Action1.putextra (" Params "," Task 1 "); StartService (action1); Intent action2 = new Intent (this, backgroundservice.class); Action2.putextra ( "Params", "Task 2"); StartService (action2); Intent action3 = new Intent (this, backgroundservice.class); Action3.putextra ("params", "Task 3"); StartService (Action3);}
We started 3 backgroundservice in the StartService () method and passed the arguments at startup. Then modify the Onhandleintent () method with the following code:
@Overrideprotected void Onhandleintent (Intent Intent) {String params = Intent.getstringextra ("params"); LOG.E (TAG, params + "in onhandleintent ()   " + thread.currentthread ()); try {thread.sleep (3000); LOG.E (TAG, params + "is finished           " + thread.currentthread ()),} catch (Exception e) {e.printstacktrace ();}}
Run the program, and the log prints the results as shown:

Observing the output shows that the execution of the onhandleintent () is orderly and the service is destroyed when all the simulated time-consuming tasks are completed. This means that we can easily use Intentservice to perform some orderly and very time-consuming asynchronous operations, and when all the tasks are executed, the Intentservice will voluntarily destroy itself, we do not need to care about intentservice destruction.

Well, now that we know the Intentservice implementation process, then we will from the source point of view of the Intentservice, look at its internal process, first look at the official website of its description:

Intentservice is a class that inherits the service to handle asynchronous requests, and the client sends requests by calling StartService (Intent). Service services will start when necessary and then process each of the intent in a worker thread, and the service services will shut down when the worker thread finishes executing.

This "Work Queue processor" is the most common pattern of separating tasks from the main thread of an application, and the Intentservice class is the classic representation of the pattern. In order to use Intentservice, it is necessary to inherit intentservice and then implement its abstract method Onhandleintent (), which receives all intent sent in the worker thread and ends itself at the appropriate time.

All requests are received in a single worker thread, and the worker thread can take time without blocking the main thread, but only one request can be processed at the same time.

After knowing the instructions of Intentservice, we continue to look at the code, first look at the definition of Intentservice member variables, the code is as follows:

Provides Message Queuing and private volatile Looper mservicelooper;//processing messages private volatile Servicehandler mservicehandler;// Represents the worker thread's name private String mname;//whether to resend Intentprivate Boolean Mredelivery;private final class Servicehandler extends Handler {public    Servicehandler (Looper Looper) {        super (Looper);    }    @Override public    void Handlemessage (Message msg) {        onhandleintent ((Intent) msg.obj);        Stopself (MSG.ARG1);    }}
Intentservice only defines 4 member variables, of which the looper type of mservicelooper children's boots should be very familiar (not familiar also I will in the next article from the source point of view on the Android message mechanism handler, Looper, message, MessageQueue, etc.), also defines the Servicehandler type of Mservicehandler,servicehandler inheritance handler, and in Handlemessage () Method calls the abstract method Onhandleintent () method and the Stopself () method that ends the service.

After understanding the member variables of Intentservice, we look at the construction method, the source code is as follows:

/** * Creates an intentservice.  Invoked by your subclass ' s constructor. * * @param name used to name of the worker thread, important only for debugging. */public Intentservice (String name) {    super ();    Mname = name;}
The constructor method of Intentservice requires that a value of type string (which represents the name of the worker thread) must be passed in, assigning the name to its member variable mname. After reading the construction method and then look at the Intentservice OnCreate () method, the source code is as follows:
@Overridepublic void OnCreate () {    //Todo:it would is nice to a partial wakelock    //during  Processing, and to has a static StartService (Context, Intent)    //method that would launch the service & hand off A wakelock.    Super.oncreate ();    Handlerthread thread = new Handlerthread ("intentservice[" + Mname + "]");    Thread.Start ();    Mservicelooper = Thread.getlooper ();    Mservicehandler = new Servicehandler (mservicelooper);}
The OnCreate () method of the parent class was first called in the OnCreate () method, followed by a handlerthread instance of thread, where there may be some doubt about the child boots, and where is the Handlerthread sacred? Do not worry, we enter the source of Handlerthread to see where it is sacred, its source code is as follows:
/** * Handy class for starting a new thread the has a looper. The looper can then is * used to create handler classes. Note that start () must still is called.    */public class Handlerthread extends Thread {int mpriority;    int mtid =-1;    Looper Mlooper;        Public Handlerthread (String name) {super (name);    mpriority = Process.thread_priority_default;     }/** * Constructs a handlerthread. * @param name * @param priority the ' priority ' to run ' the thread at '.     The value supplied must is from * {@link android.os.Process} and is from Java.lang.Thread.        */Public Handlerthread (String name, Int. priority) {super (name);    Mpriority = priority;  }/** * Call back method so can be explicitly over ridden if needed to execute some * setup before Looper     Loops.        */protected void onlooperprepared () {} public void Run () {Mtid = Process.mytid ();        Looper.prepare ();     Synchronized (this) {       Mlooper = Looper.mylooper ();        Notifyall ();        } process.setthreadpriority (mpriority);        Onlooperprepared ();        Looper.loop ();    Mtid =-1; }/** * This method returns the Looper associated with this thread. If This thread isn't been started * or for any reason are isAlive () returns False, this method would return null.       If this thread * have been started, this method would block until the Looper has been initialized.     * @return the Looper.        */Public Looper Getlooper () {if (!isalive ()) {return null;        }//If the thread has been started, wait until the Looper have been created. Synchronized (this) {while (isAlive () && mlooper = = null) {try {WA                It ();    } catch (Interruptedexception e) {}}} return mlooper; }/** * Ask the currently running Looper to QuIt.  If the thread has not * been started or have finished (that's if {@link #getLooper} returns * null), then false is  Returned.     Otherwise the Looper is asked to * Quit and true is returned.        */Public Boolean quit () {Looper Looper = Getlooper ();            if (looper! = null) {looper.quit ();        return true;    } return false; }/** * Returns The identifier of this thread.     See Process.mytid ().    */public int getthreadid () {return mtid; }}
Oh, after reading the source of Handlerthread we can rest assured that the original Handlerthread inherited from thread, that is to say Handlerthread is also an authentic thread class. The Handlerthread class has three member variables, mpriority represents the priority of the current thread (the default is 0), Mtid represents the identifier of the thread, and mlooper the role of adding message queues to the current thread and looping through the messages.

After understanding the member variable of Handlerthread, look at its overridden run () method, call Process.mytid () to Mtid in the Run () method, and then call the Looper.prepare () method to create a message queue for the current thread. After creating the message queue, assign a value to the member variable Mlooper and wake the lock mechanism that may be in the wait state, followed by the priority of the current thread, and finally into the method of Looper.loop ().

Overall Handlerthread core is to provide a thread with looper function externally, when we create the Handlerthread instance to call its start () method immediately, if not call the start () method, When we need to use Looper in Handlerthread, the thread is in a suspended state because when the Getlooper () method of the Handlerthread instance object is called, if the current thread is IsAlive () and mlooper is null, The thread will always wait (), so call its start () method immediately after the Handlerthread is created.

After reading Handlerthread source code, we then look at Intentservice's OnCreate () method, in which a handlerthread type of thread is instantiated, followed by the start () method that calls the thread, The Getlooper () method of the thread is then called to assign a value to Mservicelooper, and finally the Mservicehandler initialization is done using Mservicelooper.

After reading Intentservice's OnCreate () method, then look at the Onstartcommand () method, the source code is as follows:

/** * Should not override this method for your intentservice. Instead, * override {@link #onHandleIntent}, which the system calls when the Intentservice * receives a start request. * @see Android.app.service#onstartcommand */@Overridepublic int Onstartcommand (Intent Intent, int flags, int startid) {
   onstart (Intent, startid);    Return mredelivery? Start_redeliver_intent:start_not_sticky;}
The Onstartcommand () function calls the OnStart () function and then returns start_redeliver_intent or Start_not_sticky by determining the Mredelivery It is important to note that only one of the following three types can be returned in the Onstartcommand () function:

    • Start_not_sticky
      If the service is killed by the system after the Onstartcommand () method returns, it is not re-created until the new intent object is received. This is a secure option to avoid running the service when you don't need it.
    • Start_sticky
      If the service is killed by the system after the Onstartcommand () method returns, the system will recreate the service and attempt to invoke the Onstartcommand () method, but the system will not re-pass the last intent object. The system invokes the Onstartcommand () method with a null intent object. In this case, unless there are some intent objects being sent waiting to start the service. This applies to media players (or similar services) that do not execute the command, and it only runs indefinitely and waits for work to come.
    • Start_redeliver_intent
      If the service is killed by the system after the Onstartcommand () method returns, the system re-creates the service and invokes the Onstartcommand () method with the last intent object sent to the service. Any waiting intent objects are sent sequentially, which is appropriate for those services that should immediately resume the work being performed, such as downloading files.

Then we look at the OnStart () method, the source code is as follows:

@Overridepublic void OnStart (Intent Intent, int startid) {    Message msg = Mservicehandler.obtainmessage ();    MSG.ARG1 = Startid;    Msg.obj = Intent;    Mservicehandler.sendmessage (msg);}
In the OnStart () method, the Mservicehandler is used to send a message and the parameters passed in intent are packaged and sent together. The message that was last seen at the beginning of the article is handled in the Handlemessage () method:
Private Final class Servicehandler extends Handler {public    Servicehandler (Looper Looper) {        super (Looper);    }    @Override public    void Handlemessage (Message msg) {        onhandleintent ((Intent) msg.obj);        Stopself (MSG.ARG1);    }}
The Handlemessage () method calls the Onhandleintent () method, and then calls the Stopself () method to close the service when it finishes executing.

Overall intentservice is ideal for performing more time-consuming, orderly asynchronous operations in the background without the need for us to care about when to end the service. Handlerthread is not only a standard thread but also provides looper functionality externally, it is important to note that the start () method needs to be executed immediately after the Handlerthread is created, otherwise the thread may be in a pending state.

Well, here's the intentservice and handlerthread, thanks for watching.




Android Source Series < seven > in-depth understanding of intentservice and Handlerthread from the source point of view

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.