The original model
We know that the Service runs in the main thread, so if we perform time-consuming code operations in the Service, we need to start a child thread to handle the code. For example, we can start child threads in the onStartCommand method to handle time-consuming code.
public int onStartCommand(Intent intent, int flags, int startId) {
Thread thread = new Thread(){
@Override
public void run(a) {
/ * *
* Time-consuming code is written in child threads
* /
}
};
thread.start();
return super.onStartCommand(intent, flags, startId);
}
Copy the code
However, as we all know, once a service is started, it runs forever and must be stopped by calling stopService() or stopSelf(). So, let’s modify the run method
public void run(a) {
/ * *
* Time-consuming code is written in child threads
* /
stopSelf();
}
}
Copy the code
In this way, we can easily start a thread in the service and add stopSelf() at the end of the code; This allows the service to be terminated at the end of the code run. But is it a little bit of a hassle for us developers, it is a little bit of a hassle, like you sometimes forget to start the thread? Or forgot to call stopSelf()?
So, Google has given us a nice class that we don’t have to worry about all this stuff, because this class already does it for us to manipulate code in child threads. At the same time, when the child thread code completes, the service is automatically destroyed and no longer consumes memory resources. So, with this class, we don’t have to start the thread, and we don’t have to destroy the service. Because, this class takes care of it for us. This class is IntentService. The use of this class is similar to Service, but much easier and more convenient than Service. So let’s go straight to code, because I like to do it in code.
IntentService source
/ * *
* IntentService is a service that starts with {@linkService} is the base class to handle asynchronous requests
* The client sends the request through {@linkAndroid.content.context *#startService (Intent)}
* The service starts as needed, uses the worker thread to process each Intent thread in turn, and stops the service when the run job completes.
*
* <p> This "work queue processor" mode is typically used to unload tasks
* Main thread from the application. The IntentService class exists in
* Simplify the schema and handle the mechanism. To use it, expand
* IntentService and implement {@link #onHandleIntent(Intent)}。 IntentService
Intents will be received, the worker thread will be started, and the service will be stopped
* right.
*
* <p> All requests are processed on a worker thread - they can be
* As long as possible (and without blocking the application's main loop), but
* Only one request can be processed at a time.
*
* /
public abstract class IntentService extends Service {
// Start the thread Looper
private volatile Looper mServiceLooper;
// A handler for sending and processing messages
private volatile ServiceHandler mServiceHandler;
// Name of the child thread
private String mName;
// Whether it can be sent repeatedly
private boolean mRedelivery;
// Handle the message handler implementation
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
/ / the child thread
// Leave abstract methods to subclasses to override
onHandleIntent((Intent)msg.obj);
// Stop the service when the child task is finished
stopSelf(msg.arg1);
}
}
/ * *
* Constructor
* @paramName Worker Thread name useful for debugging
* /
public IntentService(String name) {
super(a);
mName = name;
}
/ * *
*
* Sets intent redelivery preferences. Usually called from the constructor
* with your preferred semantics.
* Sets the intent replay preference, usually in the constructor call
*
*
* If set to true, {@link#onStartCommand(Intent, int, int)}@link Service#START_REDELIVER_INTENT}
Therefore, if the process dies before onHandleIntent returns, the process will be restarted and the intent will be sent
* If multiple intents are sent, only the most recent one will be guaranteed to be resent
*
* If set to false, {@link#onStartCommand(Intent, int, int)}@link Service#START_NOT_STICKY}
* If the process dies, the intent is dead
*
* /
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate(a) {
super.onCreate();
// Start a thread with HandlerThread and generate looper and message queue
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
// Get the looper of the above child thread
mServiceLooper = thread.getLooper();
// Initialize handler
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(Intent intent, int startId) {
// Onstart sends a message to handle
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
// Whether it can be sent repeatedly
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy(a) {
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 executed in child threads and can only execute one event at a time,
* /
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
}
Copy the code
Summary: IntentServices is a way to use Service+ HandlerThread. In many cases we can use HandlerThread+ Handler for thread execution and handler distribution of messages.