Android source code parsing (4) --) IntentService

Source: Internet
Author: User

Android source code parsing (4) --) IntentService

What is IntentService? In short, IntentService is a Service that contains its own message loops. First, it is a service. Therefore, services have its own characteristics and some of its own attributes, it encapsulates a message queue and a HandlerThread. In its specific abstract method, the onHandleIntent method runs in its message queue thread, let's take a look at its simple usage:

Define an IntentService
public class MIntentService extends IntentService{    public MIntentService() {        super("");    }    @Override    protected void onHandleIntent(Intent intent) {        Log.i("tag", intent.getStringExtra("params") + "  " + Thread.currentThread().getId());    }}
Define service in androidManifest. xml

  
Start this service
title.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent(MainActivity.this, MIntentService.class);                intent.putExtra("params", "ceshi");                startService(intent);            }        });

When you click the title component, the service receives the message and prints the intent parameter passed in. It also shows that the thread ID of the onHandlerIntent method execution is not the main thread. Why?

Let's take a look at the source code of the service:

public abstract class IntentService extends Service {    private volatile Looper mServiceLooper;    private volatile ServiceHandler mServiceHandler;    private String mName;    private 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);        }    }    /**     * 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 would be nice to have an option to hold a partial wakelock // during processing, and to have 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); } @Override public void onStart(Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); } /** * You 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 */ @Override public int onStartCommand(Intent intent, int flags, int startId) { onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; } @Override public void onDestroy() { mServiceLooper.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 should not call {@link #stopSelf}. * * @param intent The value passed to {@link * android.content.Context#startService(Intent)}. */ @WorkerThread protected abstract void onHandleIntent(Intent intent); }

The code is quite concise. First, we can know that IntentService is a Service and an abstract class through definition. Therefore, we need to implement the abstract method onHandlerIntent when inheriting IntentService.

The onCreate method is as follows:

@Override    public void onCreate() {        // TODO: It would be nice to have an option to hold a partial wakelock        // during processing, and to have 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);    }

We can find that it internally defines a HandlerIThread (essentially a thread containing a Message Queue)
Then, maintain the Looper and Handler using the member variables. Because the Handler is associated with the Looper object of the HandlerThread, The handMessage method of the Handler is executed in the HandlerThread.

Then we find that the onStartCommand method is the onStart method called. Let's take a look at its onStart method:

@Override    public void onStart(Intent intent, int startId) {        Message msg = mServiceHandler.obtainMessage();        msg.arg1 = startId;        msg.obj = intent;        mServiceHandler.sendMessage(msg);    }

It is easy to say that startId and intent objects received at startup are transferred to the Message Queue for processing. Let's take a look at the processing logic of the Message Queue:

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);        }    }

We can see that the handleMessage method executes two logics internally. One is to call its onHandlerIntent abstract method, by analyzing the creation process of its onCreate method handler object, we know that its handler object is attached to the HandlerThread, so its handeMessage method is also executed in the HandlerThread thread, this confirms a conclusion in the preceding example that onHandlerIntent is executed in the Child thread.
Then the stopSelf method is called. Note that the stopSelf method passes msg. the arg1 parameter. From the onStart method, we can know that we have passed startId. Refer to other articles, we know that because the service can start N times and transmit N messages, when a message queue of IntentService contains a message, calling stopSelf (startId) does not stop itself immediately. Only when the last message in the message queue is completed will it actually stop itself.

Through the above examples and related descriptions, we can know:

IntentService is a service and an abstract class;

Inherit IntentService and implement its onHandlerIntent abstract method;

OnHandlerIntent is executed in the Child thread;

IntentService stores a member variable, such as HandlerThread, logoff, and Handler, to maintain its own message queue;

Every time the IntentService background task is executed, it will attempt to close itself, but it will stop itself only when the last message in the IntentService message queue is executed;

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.