In Android development, we usually put some time-consuming operations in a Service, but the default Service is running in the main thread, we can not directly in the main thread to perform time-consuming operations, so we need to maintain a child thread in the Service, which is relatively troublesome. To solve this problem, Google provides an IntentService. Compared to a normal Service, IntentService automatically creates a child thread to execute the task, and when the task is finished, IntentService automatically shuts down the Service. It’s very convenient to use.
IntentService IntentService IntentService IntentService IntentService IntentService
public class IntentServiceExample extends IntentService {
IntentService(String name); IntentService(String name); IntentService(String name)
public IntentServiceExample(a) {
super("IntentServiceExample");
}
/** * Override the onHandleIntent method of the parent class and implement the business logic you need in that method */
@Override
protected void onHandleIntent(@Nullable Intent intent) {
try {
Log.e("Test", Thread.currentThread().getName() + ":task start");
Thread.sleep(3000);// Let the thread sleep for 3 seconds to simulate time-consuming tasks
Log.e("Test", Thread.currentThread().getName() + ":task finish");
} catch(InterruptedException e) { e.printStackTrace(); }}}Copy the code
IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService: IntentService
Intent intent = new Intent(MainActivity.this,IntentServiceExample.class);
startService(intent);
Copy the code
The onHandleIntent method runs in a child thread:
E/Test: IntentService[IntentServiceExample]:task start
E/Test: IntentService[IntentServiceExample]:task finish
Copy the code
Note that IntentService also needs to be registered in the AndroidManifest file to use IntentService, otherwise IntentService will not work properly.
##HandlerThread
Now that we know how IntentService works, let’s take a look at a class called HandlerThread. Since HandlerThread is an important object in IntentService, understanding how HandlerThread works can help you learn how IntentService works.
As we can see from the name of HandlerThread, HandlerThread should inherit from the Thread class, and therefore be a Thread itself. The run method is an important method in HandlerThread. Let’s look at the source code of the run method:
public class HandlerThread extends Thread {
Looper mLooper;
@Override
public void run(a) {
mTid = Process.myTid();
Looper.prepare(); // Call Looper's prepare method
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop(); // Call Looper's loop method
mTid = -1; }... }Copy the code
As you can see, Looper’s prepare and loop methods are called in the run method of the HandlerThread. A HandlerThread has a message loop on by default. A HandlerThread has a message loop on by default. (For those who do not know about the messaging system in Android, you can go to my other blog ————Handler, MessageQueue and Looper)
HandlerThread also provides a getLooper method to retrieve the thread’s Looper:
public Looper getLooper(a) {
if(! isAlive()) {return null;
}
// If the thread has been started, but the message loop has not yet started, wait until the message loop system is started
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
Copy the code
IntentService is an example of a HandlerThread. Let’s look at how IntentService works.
How IntentService works
Now that we know about handlerThreads, we can finally analyze how IntentServices work. IntentService IntentService IntentService IntentService IntentService IntentService
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatileServiceHandler mServiceHandler; .// Omit part of the code
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); }}@Override
public void onCreate(a) {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public void onDestroy(a) {
mServiceLooper.quit();
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
Copy the code
As you can see, IntentService inherits from Service, so IntentService naturally owns all the lifecycle methods of Service as well. Let’s first look at the onCreate method:
@Override
public void onCreate(a) {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
Copy the code
You can see that the onCreate method first creates and starts a HandlerThread object. We’ve already looked at how handlerThreads work, and we know that this HandlerThread has its messaging system enabled by default. GetLooper (); getLooper (); mServiceHandler (); mServiceHandler (); So messages sent through mServiceHandler will eventually be executed in this HandlerThread. (If you are not familiar with The Handler and messaging system in Android, I suggest you to read another of my blog ————Handler, MessageQueue and Looper).
Then let’s look at the onStart method of IntentService:
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
Copy the code
The code for the onStart method is simple, sending a message through the mServiceHandler that was initialized in onCreate. Let’s look at the mServiceHandler code:
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); }}Copy the code
You can see that the onHandleIntent method is called directly from the handleMessage method of ServiceHandler. Since mServiceHandler is created using the Looper of the HandlerThread thread, So the onHandleIntent method will be executed in the HandlerThread.
IntentService terminates the service by calling stopSelf after the onHandleIntent method is executed. IntentService is an “out of the way” service, so we don’t need to end the service manually.
Note that IntentService’s onBind method returns null by default, so we do not recommend using the bindService method to bind IntentService:
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
Copy the code
Since Android8.0, Google has strengthened the restrictions on background services. When the app is in the background, you cannot start the background service with startService. IntentService is also affected by this restriction. Google recommends using JobIntentService instead of IntentService.