[Android Notes] IntentService source code analysis, Android intentservice
The Service components must be familiar. Note that the Service component runs in the UI thread by default, so it also blocks the main thread. during use, remember not to perform time-consuming operations in the Service. Instead, you should create sub-threads and execute them asynchronously.The IntentService class encapsulates the work of creating sub-threads in the Service (in fact, HandlerThread is created). We only need to inherit the IntentService and rewrite its onHandleIntent method. The onHandleIntent method runs in the sub-thread, the Intent parameter of this method comes from onStart or onStartCommand, that is, we can put the logic that should be written in the onStart method into onHandleIntent.
I. ExampleCreate a Service as follows: Note: in actual development, you only need to rewrite the onHandleIntent method. Here, we want to observe its lifecycle.
Package com. example. intentservicedemo; import android. app. intentService; import android. content. intent; import android. util. log; public class MyIntentService extends IntentService {private static final String TAG = "MyIntentService"; public MyIntentService () // note that no parameter constructor {super ("MyIntentService ");} @ Overrideprotected void onHandleIntent (Intent intent) {int data = intent. getIntExtra ("TEST",-1); Log. I (TAG, "data =" + data); switch (data) {case 1: Log. I (TAG, "service run task 1... "); try {Thread. sleep (3000);} catch (InterruptedException e) {e. printStackTrace ();} break; case 2: Log. I (TAG, "service run task 2... "); break ;}@overridepublic void onCreate () {super. onCreate (); Log. I (TAG, "oncreate... ") ;}@ Overridepublic void onStart (Intent intent, int startId) {super. onStart (intent, startId); Log. I (TAG, "onstart... ") ;}@ Overridepublic int onStartCommand (Intent intent, int flags, int startId) {Log. I (TAG, "onstartcommand... "); return super. onStartCommand (intent, flags, startId) ;}@ Overridepublic void onDestroy () {super. onDestroy (); Log. I (TAG, "ondestroy... ");}}
Configure it in the configuration file:
<service android:name="com.example.intentservicedemo.MyIntentService"></service>
Create an Activity:
package com.example.intentservicedemo;import android.app.Activity;import android.content.Intent;import android.os.Bundle;public class MainActivity extends Activity{@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this,MyIntentService.class);intent.putExtra("TEST",1);startService(intent);intent.putExtra("TEST",2);startService(intent);}}
Observe the log:
After the event is handled, the service will be destroyed.
Ii. Source Code AnalysisIntentService encapsulates the subthread message loop:
Private volatile low.mservicelow.; // low.private volatile ServiceHandler mServiceHandler; // Handler private String mName; // The subthread name is private boolean mRedelivery;
ServiceHandler is a subclass of Handler:
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); } }
Call the onHandleIntent method in handleMessage,
After the service is completed, call stopSelf to destroy the service.. The message loop is created in the onCreate method:
public void onCreate() { super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }
A subthread HandlerThread is created in the onCreate method, and a message loop is created using the logoff provided by HandlerThread.
In the onStart method, Intent is sent to Handler as a message and finally handled by the onHandleIntent method:
public void onStart(Intent intent, int startId) { 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); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; }
Calling the destroy method will destroy the message loop and terminate the subthread:
@Override public void onDestroy() { mServiceLooper.quit(); }
------------------------------------- Appendix: I have a question. In the preceding example, startService is executed twice. The source code is analyzed, and the handleMessage of Handler is processed. After handleMessage is executed, the onHandleIntent method is executed, the stopSelf destroy service should be called. Therefore, destroy should be performed twice in the log, but only once destroy is actually executed. Why?
We noticed that the stopSelf parameter of the handleMessage method has a startId parameter, that is, to stop a service with a specific startId. The startId of startService is different in the preceding two times, so the service will not stop.Print startId twice
:
Document explanation:
However, if your service handles multiple requests to onStartCommand () concurrently, then you shouldn't stop the service when you're done processing a start request, because you might have since received ed a new start request (stopping at the end of the first request wocould terminate the second one ). to avoid this problem, you can use stopSelf (int) to ensure that your request to stop the service is always based on the most recent start request. that is, when you call stopSelf (int), you pass the ID of the start request (the startId delivered to onStartCommand () to which your stop request corresponds. then if the service was Ed a new start request before you were able to call stopSelf (int), then the ID will not match and the service will not stop.
Who has the source code of the Forum for Android bus? Do not use the front-end or the back-end?
Source code I have content to add myself
Upload the source code of Android 44
Hello, this is my uncompressed source code size. You can do it yourself. The source code is indeed large.