[Android] Android IntentService source code analysis

Android IntentService source code analysis

1. Introduction

Service is one of the four major components of Android. It is used to run in the background, but because Service is still running on the main thread, time-consuming operations cannot be performed directly. If there is a time-consuming operation, you still need to put it in the child thread, you can manually start the thread, or you can use a very simple class IntentService provided by Android. The source code of this class is still very simple, this article analyzes its implementation.

二、HandlerThread

Before analyzing IntentService, we must first understand HandlerThread. By looking at the name, you know that this class is a thread class related to Handler. The API describes it like this:
Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.
It is a helper class for creating threads with Looper objects. Looper objects can be used to create Handler classes. Of course, start() is still called to start the thread.
In the principle of Android Handler in the last article, we know that when a thread creates a Handler, it must have a Looper object, and use Looper to open the message loop. In the main thread, the system has done this for us. So if in other child threads, how should we create Looper? Look at the run() method of HandlerThread:

public void run() {
    
    
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
    
    
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

Looper.prepare() is called in this method to obtain the Looper object for the thread and save the object. Then call Looper.loop() to start the message loop. In this method, there is an infinite loop that continuously takes out messages from the message queue, so the message system of this thread is established. These have been analyzed in the previous article.

Three, IntentService

Figure out HandlerThread, IntentService is very simple. IntentService uses HandlerThread internally. IntentService inherits Service and is an abstract class. Here is its onCreate() method:

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

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

A HandlerThread object is created in this method, and its Looper is obtained, and then the Handler is created with this Looper. The handleMessage method of IntentService transfers the received message to onHandleIntent for processing. This method is an abstract method, and it is also a method that needs to be rewritten when we use IntentService. After onHandleIntent is processed, IntentService will call stopSelf() to automatically stop. handleMessage will be called in the Looper.loop() method and run in HandlerThread, so time-consuming operations can be handled safely.
How did the news come? Take a look at the source code of onStartCommand():

public int onStartCommand(Intent intent, int flags, int startId) {
    
    
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
public void onStart(Intent intent, int startId) {
    
    
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

Very simple, wrap the intent parameter into the obj of the message, and then send the message. The Intent here is the Intent in startService(Intent) when the service is started.
For Service, when startService(Intent) is called multiple times, the onCreate() method will only be called once, so some initialization work is done here, and onStartCommand will be called multiple times accordingly. Therefore, as long as the Intent parameters are different, different tasks can be completed.

Four, summary

As can be seen from the above analysis, as long as you understand the principle of Handler, IntentService is better understood. There are several points to note when using IntentService:
 Cannot interact with UI directly. In order to reflect the results of its execution on the UI, the results need to be returned to the Activity.
 The work task queue is executed sequentially. If a task is being executed in the IntentService, and you send a new task request at this time, the new task will wait until the previous task is completed before it starts executing.
The task in progress cannot be interrupted.

Guess you like

Origin blog.csdn.net/sinat_36955332/article/details/108278905