Android IntentService source code analysis

Source: Internet
Author: User

Android IntentService source code analysis
IntentService Introduction: IntentService is. startService (Intent) starts a Service that can process asynchronous requests. When using this Service, you only need to inherit the IntentService and override the onHandleIntent (Intent) method to receive an Intent object, this service will automatically stop the service when the asynchronous task is completed. all requests are processed in the internal work thread of IntentService. They execute tasks sequentially (but do not block the execution of the main thread), and only one asynchronous request can be executed at a certain time.

IntnetService features: 1. You do not need to start a thread in the Service to process time-consuming tasks. 2. You do not need to manually stop the Service.
IntentService example: the server code is as follows:

Package com. xjp. broadcast; import android. app. intentService; import android. content. intent; import android. util. log;/*** Description: * User: xjp * Date: 2015/5/4 * Time: */public class MyIntentService extends IntentService {private static final String TAG = "MyIntentService "; /*** Creates an IntentService. invoked by your subclass's constructor. ** @ param name Used to name the worker thread, important only for debugging. */public MyIntentService () {super ("TEST") ;}@ Override public void onCreate () {Log. e (TAG, "==== onCreate ="); super. onCreate () ;}@ Override public void onDestroy () {Log. e (TAG, "==== onDestroy ="); super. onDestroy () ;}@ Override public int onStartCommand (Intent intent, int flags, int startId) {Log. e (TAG, "==== onStartCommand ="); Log. e (TAG, "=== Current Thread Id =" + Thread. currentThread (). getId (); return super. onStartCommand (intent, flags, startId) ;}@ Override protected void onHandleIntent (Intent intent) {Log. e (TAG, "=== onHandleIntent ="); Log. e (TAG, "=== Current Thread Id =" + Thread. currentThread (). getId ();/*** simulate time-consuming task execution here */try {Thread. sleep (2000);} catch (InterruptedException e) {e. printStackTrace ();} int key = intent. getIntExtra ("key", 0); Log. e (TAG, "==== the key is =" + key );}}


The client code is as follows:
package com.xjp.broadcast;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Button;public class MainActivity extends Activity {    private Button startService;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        startService = (Button) findViewById(R.id.startService);        startService.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent service2 = new Intent(MainActivity.this, MyIntentService.class);                service2.putExtra("key", 3);                startService(service2);            }        });    }    @Override    protected void onResume() {        super.onResume();        Intent service = new Intent(this, MyIntentService.class);        service.putExtra("key", 1);        startService(service);        Intent service1 = new Intent(this, MyIntentService.class);        service1.putExtra("key", 2);        startService(service1);    }    @Override    protected void onDestroy() {        super.onDestroy();    }}

After the application is started, print as follows:


We found that the service was started twice, onCreate was executed once, onStartCommand was executed twice, and Thread id = 1, which indicates that the service was executed in the UI Thread, the onHandleIntent and Thread id = 234 are executed twice. This indicates that the abstract method onHandleIntent is executed in the Child Thread. Therefore, time-consuming tasks can be executed in this method. And you will find that when the second task is executed, the output onDestory indicates that the service is stopped automatically without human intervention.
Why is onHandleIntent executed in a child thread? When did I create a subthread? Why can IntentService execute asynchronous time-consuming tasks in onHandleIntent? Why does the Service stop automatically after the task is executed ?? Next, let's unlock the secret from the source code perspective !!!
IntentService source code analysis:
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.app;import android.content.Intent;import android.os.Handler;import android.os.HandlerThread;import android.os.IBinder;import android.os.Looper;import android.os.Message;/** * IntentService is a base class for {@link Service}s that handle asynchronous * requests (expressed as {@link Intent}s) on demand.  Clients send requests * through {@link android.content.Context#startService(Intent)} calls; the * service is started as needed, handles each Intent in turn using a worker * thread, and stops itself when it runs out of work. * * 

This "work queue processor" pattern is commonly used to offload tasks * from an application's main thread. the IntentService class exists to * simplify this pattern and take care of the mechanic. to use it, extend * IntentService and implement {@ link # onHandleIntent (Intent )}. intentService * will receive the Intents, launch a worker thread, and stop the service as * appropriate. **

All requests are handled on a single worker thread -- they may take as * long as necessary (and will not block the application's main loop ), but * only one request will be processed at a time. **

* Developer Guides *

For a detailed discussion about how to create services, read the * Services developer guide.

* ** @ See android. OS. asyncTask */public abstract class IntentService extends Service {private volatile low.mservicelow.private volatile ServiceHandler mServiceHandler; private String mName; private boolean mRedelivery; private final class ServiceHandler extends Handler {public ServiceHandler (Looper loler) {super (looper) ;}@ Override public void handleMessage (Message msg) {onHandleIntent (Intent) msg. obj); stopSelf (msg. arg1) ;}}/*** Creates an IntentService. invoked by your subclass's constructor. ** @ param name Used to name the worker thread, important only for debugging. */public IntentService (String name) {super (); mName = name;}/*** Sets intent redelivery preferences. usually called from the constructor * with your preferred semantics. **

If enabled is true, * {@ link # onStartCommand (Intent, int, int)} will return * {@ link Service # START_REDELIVER_INTENT }, so if this process dies before * {@ link # onHandleIntent (Intent)} returns, the process will be restarted * and the intent redelivered. if multiple Intents have been sent, only * the most recent one is guaranteed to be redelivered. **

If enabled is false (the default), * {@ link # onStartCommand (Intent, int, int)} will return * {@ link Service # START_NOT_STICKY}, and if the process dies, the Intent * dies along with it. */public void setIntentRedelivery (boolean enabled) {mRedelivery = enabled;} @ Override public void onCreate () {// TODO: it wocould be nice to have an option to hold a partial wakelock // during processing, and to ha Ve a static startService (Context, Intent) // method that wowould launch the service & hand off a wakelock. super. onCreate (); HandlerThread thread = new HandlerThread ("IntentService [" + mName + "]"); thread. start (); mserviceloading = thread. getLooper (); mServiceHandler = new ServiceHandler (mserviceloader) ;}@ Override public void onStart (Intent intent, int startId) {Message msg = mServiceHandler. obta InMessage (); msg. arg1 = startId; msg. obj = intent; mServiceHandler. sendMessage (msg);}/*** You shocould not override this method for your IntentService. instead, * override {@ link # onHandleIntent}, which the system CILS when the IntentService * es a start request. * @ see android. app. service # onStartCommand */@ Override public int onStartCommand (Intent intent, int flags, int startId) {onStar T (intent, startId); return mRedelivery? START_REDELIVER_INTENT: START_NOT_STICKY;} @ Override public void onDestroy () {mserviceloading. quit ();}/*** Unless you provide binding for your service, you don't need to implement this * method, because the default implementation returns null. * @ see android. app. service # onBind */@ Override public IBinder onBind (Intent intent) {return null;}/*** This method is invoked on the worker thread with a request to process. * Only one Intent is processed at a time, but the processing happens on a * worker thread that runs independently from other application logic. * So, if this code takes a long time, it will hold up other requests to * the same IntentService, but it will not hold up anything else. * When all requests have been handled, the IntentService stops itself, * so you shoshould not call {@ link # stopSelf }. ** @ param intent The value passed to {@ link * android. content. context # startService (Intent )}. */protected abstract void onHandleIntent (Intent intent );}


Let's look at the source code line 107--111: IntentService implements a thread with a cyclic Message Processing Mechanism in HandlerThread. For the principles and usage of HandlerThread, see Android HandlerThread source code analysis. Therefore, IntentService also implements a thread with a cyclic message processing mechanism. Let's see how the time-consuming tasks on our client are passed to the internal HandlerThread thread of IntentService for execution? Each time the service is started, onStartCommand is executed.
Let's take a look at line 1 of the source code: The onStart method is called.
Let's look at the source code 115--120 line: onStart method implementation. In this method, we encapsulate the Intent passed by the client, and use the Handler + Message processing mechanism mServiceHandler. sendMessage (msg); the time-consuming task passed to the HandlerThread subthread to execute the client. Let's look at the implementation of mServiceHandler.
Line 8-68 of the source code: mServiceHandler is implemented to form a Handler + Message + logoff cyclic Message processing mechanism.
Line 2 of source code: calls the onHandlerIntent abstract method with the Intent Message Parameter of the client. This abstract method is left to the subclass to implement the corresponding asynchronous time-consuming task. Therefore, the inherited IntentService subclass must implement the onHandlerIntent abstract method.
Line 2 of source code: The stopSelf () method is called. After the asynchronous task is executed, the Servvice is automatically stopped. Therefore, the client does not need to manually stop the Service.
IntentService summary:
IntentService analysis is complete. 1. In fact, a thread with a cyclic message processing mechanism is implemented internally to process time-consuming tasks in the background, without the need to implement a thread to execute time-consuming tasks. 2. After the task is executed, stopSelf is automatically called to stop the service. You do not need to manually manage the service from the client. The client only needs to start the task again when the asynchronous background time-consuming task needs to be executed. 3. If you have some knowledge about HandlerThread, you will know why IntentService executes asynchronous tasks in sequence and can only execute one task at a time. Because HandlerThread + Handler is a single working thread, that is, when the client simultaneously places two asynchronous tasks, the next task can be executed only after the previous task is completed, the second task will block waiting. But it is executed in the Child thread and does not affect the UI thread, so there will be no ANR.

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.