Article Contents:
1, define,
What is an IntentService?
Official documents:
IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through Context.startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, And stops themselves when it runs out of work. This “Work queue processor” pattern is commonly used to offload tasks from an application’s main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, And stop the service as appropriate. All requests are handled on a single worker thread — they may take as long as it is handled necessary (and will not block the application’s main loop), but only one request will be processed at a time.
From my understanding:
IntentService is a base class of Services that can handle asynchronous requests as needed. The client calls context. startService(Intent) to send a request. IntentService starts as needed, uses a worker thread to handle each Intent in turn, and stops itself when the work fails. This “work queue processing” mode is typically used to lighten the workload on the main thread of an application. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive Intents, start the worker thread, and stop the service as needed. All requests are processed on a worker thread – they may take as long as they want (and do not block the application’s main loop), but only one request can be processed at a time.
IntentService can handle asynchronous requests. The worker thread in IntentService processes each Intent in turn, and only one request at a time. 3, implement onHandleIntent(Intent) to receive the Intent task.
2. IntentService features
(1) With its own working thread, time-consuming operations can be directly executed without ANR problems. (2) Force tasks to be executed in sequence. (3) The IntentService is automatically closed after the task is completed.
3. IntentService usage scenario
IntentService is suitable for handling short-term, lightweight, time-consuming background tasks and tasks that need to be executed sequentially. For example, a task can be completed after uploading a few images in the background, and it needs to be uploaded in order. As a counterexample, things like background music playback are not short-term, lightweight background tasks and are not suitable for IntentService.
4. Example (Kotlin)
4.1 create IntentService
4.1.1 Interpretation of Demo:
Override onHandleIntent(…) Function to start the task according to the incoming Intent action. 2. Provide startActionFoo() and startActionBaz() interfaces for external start tasks. Create handleActionFoo() and handleActionBaz() to handle the task. A 30-second delay was added to both methods to test IntentService’s asynchronous processing capabilities.
4.1.2 Interpretation of work process:
After an external call to startActionFoo() or startActionBaz(), MyIntentService is launched and onHandleIntent(…) is called. OnHandleIntent determines which method to handle first based on the timing of the call. In this example, startActionFoo() is executed first and then startActionBaz() is executed.
1private const val ACTION_FOO = "blog.intentservice.action.FOO"
2private const val ACTION_BAZ = "blog.intentservice.action.BAZ"
3private const val EXTRA_PARAM = "blog.intentservice.extra.PARAM"
4private const val TAG = "MyIntentService"
5class MyIntentService : IntentService("MyIntentService") {
6 override fun onHandleIntent(intent: Intent?). {
7 when(intent? .action) {
8 ACTION_FOO -> {
9 val param = intent.getStringExtra(EXTRA_PARAM)
10 handleActionFoo(param)
11 }
12 ACTION_BAZ -> {
13 val param = intent.getStringExtra(EXTRA_PARAM)
14 handleActionBaz(param)
15 }
16 }
17 }
18 override fun onCreate(a) {
19 super.onCreate()
20 Log.i(TAG, "onCreate")
21 }
22 override fun onStartCommand(intent: Intent? , flags:Int, startId: Int): Int {
23 Log.i(TAG, "onStartCommand")
24 return super.onStartCommand(intent, flags, startId)
25 }
26 override fun onStart(intent: Intent? , startId:Int) {
27 Log.i(TAG, "onStart")
28 super.onStart(intent, startId)
29 }
30 override fun onDestroy(a) {
31 Log.i(TAG, "onDestroy")
32 super.onDestroy()
33 }
34 / * *
35* Handle the Foo event
36* /
37 private fun handleActionFoo(param: String) {
38 Log.i(TAG, "handleActionFoo")
39 Thread.sleep(30 * 1000) // Delay execution for 30 seconds
40 Log.i(TAG, "handleActionFoo end")
41 }
42 / * *
43* Handle Baz events
44* /
45 private fun handleActionBaz(param: String) {
46 Log.i(TAG, "handleActionBaz")
47 Thread.sleep(30 * 1000) // Delay execution for 30 seconds
48 Log.i(TAG, "handleActionBaz end")
49 }
50 companion object {
51 var intent: Intent? = null
52 / * *
53* Provides external start startActionFoo event handling
54* /
55 @JvmStatic
56 fun startActionFoo(context: Context, param: String) {
57 intent = Intent(context, MyIntentService::class.java).apply {
58 action = ACTION_FOO
59 putExtra(EXTRA_PARAM, param)
60 }
61 context.startService(intent)
62 }
63 / * *
64* Provides start startActionBaz event handling to the outside world
65* /
66 @JvmStatic
67 fun startActionBaz(context: Context, param: String) {
68 intent = Intent(context, MyIntentService::class.java).apply {
69 action = ACTION_BAZ
70 putExtra(EXTRA_PARAM, param)
71 }
72 context.startService(intent)
73 }
74 / * *
75* Provide stopService externally
76* /
77 fun stopSelfService(context: Context) {
78 if(intent ! =null) {
79 context.stopService(intent)
80 }
81 }
82 }
83}
Copy the code
Finally, don’t forget to register IntentService in androidmanifest.xml
<service
android:name="blog.intentservice.MyIntentService"
android:exported="false" />
Copy the code
4.2 Starting IntentService on the Client
Start the startActionFoo() and startActionBaz() tasks on the client.
1 class TestIntentServiceActivity : AppCompatActivity() {
2 override fun onCreate(savedInstanceState: Bundle?). {
3 super.onCreate(savedInstanceState)
4 setContentView(R.layout.activity_test_intent_service)
5 MyIntentService.startActionFoo(this."task_foo")
6 MyIntentService.startActionBaz(this."task_baz")
7 }
8 }
Copy the code
4.3 Workflow analysis
4.3.1 IntentService Life Cycle
The figure shows the life cycle diagram of a Service. You might wonder why you use a Service lifecycle diagram instead of an IntentService lifecycle diagram. The simple reason is that an IntentService inherits from a Service, so its lifecycle is essentially the same as the Service lifecycle. However, since onBind() returns null by default in IntentService, the Call to bindService content is not needed. For IntentService, we only care about the left side of Call to startService.
4.3.2 Example workflow
Take a look at the complete workflow in this example.
OnCreate – > onStartCommand – > onStart – > handleActionFoo – > onStartCommand – > onStart – > handleActionBaz – > onDestroy
You can identify features in IntentService that execute tasks sequentially and have features that can execute time-consuming tasks. ANR is guaranteed if you use Service to delay execution by 20 seconds.
4.4 Analysis of Special Scenarios
If you force StopService before the handleActionFoo task ends, the current IntentService is destroyed, but its worker thread continues execution. Log printing sequence:
OnCreate -> onStartCommand -> onStart -> handleActionFoo -> onDestroy -> handleActionFoo end
If stopService is forced before the handleActionFoo task ends and handleActionBaz task starts, the two tasks will execute in different worker threads. However, since it is on a different worker thread, there is no way to determine which task completes first.
IntentService source code analysis
Look at the question with a doubt (1) How to implement the worker thread? (2) How to execute tasks in sequence? (3) How to realize the automatic judgment of Service closing time?
5.1 IntentService source
IntentService is a Service that has the same life cycle as a Service. IntentService has a worker thread that executes the task using onHandleIntent.
Note: It is not recommended to start an IntentService with bindService() because onBind() always returns null in IntentService.
1 public abstract class IntentService extends Service {
2 private volatile Looper mServiceLooper;
3 private volatile ServiceHandler mServiceHandler;
4 private String mName;
5 private boolean mRedelivery;
6 private final class ServiceHandler extends Handler {
7 public ServiceHandler(Looper looper) {
8 super(looper);
9 }
10 @Override
11 public void handleMessage(Message msg) {
12 onHandleIntent((Intent)msg.obj);
13 stopSelf(msg.arg1);
14 }
15 }
16 / * *
17 * Creates an IntentService. Invoked by your subclass's constructor.
18 *
19 * @param name Used to name the worker thread, important only for debugging.
20* /
21 public IntentService(String name) {
22 super(a);
23 mName = name;
24 }
25 / * *
26 * Sets intent redelivery preferences. Usually called from the constructor
27 * with your preferred semantics.
28 *
29 * <p>If enabled is true,
30 * {@link #onStartCommand(Intent, int, int)} will return
31 * {@link Service#START_REDELIVER_INTENT}, so if this process dies before
32 * {@link #onHandleIntent(Intent)} returns, the process will be restarted
33 * and the intent redelivered. If multiple Intents have been sent, only
34 * the most recent one is guaranteed to be redelivered.
35 *
36 * <p>If enabled is false (the default),
37 * {@link #onStartCommand(Intent, int, int)} will return
38 * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent
39 * dies along with it.
40* /
41 public void setIntentRedelivery(boolean enabled) {
42 mRedelivery = enabled;
43 }
44 @Override
45 public void onCreate(a) {
46 // TODO: It would be nice to have an option to hold a partial wakelock
47 // during processing, and to have a static startService(Context, Intent)
48 // method that would launch the service & hand off a wakelock.
49 super.onCreate();
50 HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
51 thread.start();
52 mServiceLooper = thread.getLooper();
53 mServiceHandler = new ServiceHandler(mServiceLooper);
54 }
55 @Override
56 public void onStart(@Nullable Intent intent, int startId) {
57 Message msg = mServiceHandler.obtainMessage();
58 msg.arg1 = startId;
59 msg.obj = intent;
60 mServiceHandler.sendMessage(msg);
61 }
62 / * *
63 * You should not override this method for your IntentService. Instead,
64 * override {@link #onHandleIntent}, which the system calls when the IntentService
65 * receives a start request.
66 * @see android.app.Service#onStartCommand
67* /
68 @Override
69 public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
70 onStart(intent, startId);
71 return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
72 }
73 @Override
74 public void onDestroy(a) {
75 mServiceLooper.quit();
76 }
77 / * *
78 * Unless you provide binding for your service, you don't need to implement this
79 * method, because the default implementation returns null.
80 * @see android.app.Service#onBind
81* /
82 @Override
83 @Nullable
84 public IBinder onBind(Intent intent) {
85 return null;
86 }
87 / * *
88 * This method is invoked on the worker thread with a request to process.
89 * Only one Intent is processed at a time, but the processing happens on a
90 * worker thread that runs independently from other application logic.
91 * So, if this code takes a long time, it will hold up other requests to
92 * the same IntentService, but it will not hold up anything else.
93 * When all requests have been handled, the IntentService stops itself,
94 * so you should not call {@link #stopSelf}.
95 *
96 * @param intent The value passed to {@link
97 * android.content.Context#startService(Intent)}.
98 * This may be null if the service is being restarted after
99 * its process has gone away; see
100 * {@link android.app.Service#onStartCommand}
101 * for details.
102* /
103 @WorkerThread
104 protected abstract void onHandleIntent(@Nullable Intent intent);
105}
Copy the code
5.2 How to implement IntentService worker thread?
IntentService creates a HandlerThread in onCreate(), which completes the entire worker thread.
1 @Override
2public void onCreate(a) {
3 super.onCreate();
4 HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
5 thread.start();
6.
7}
Copy the code
5.3 How can I Perform tasks in sequence?
IntentService contains an inner class of ServiceHandler, which is essentially a Handler. We then get the Looper of the HandlerThread in onCreate, associated with the HandlerThread. OnStart (…) is called when the task to be executed is added to IntentService. Function, which then sends the task message to ServiceHandler, forming a message queue, thus ensuring that the tasks are executed in sequence.
1@Override
2public void onCreate(a) {
3 super.onCreate();
4.
5 mServiceLooper = thread.getLooper();
6 mServiceHandler = new ServiceHandler(mServiceLooper);
7}
8
9private final class ServiceHandler extends Handler {
10 public ServiceHandler(Looper looper) {
11 super(looper);
12 }
13 @Override
14 public void handleMessage(Message msg) {
15 onHandleIntent((Intent)msg.obj);
16 stopSelf(msg.arg1);
17 }
18}
19
20@Override
21public void onStart(@Nullable Intent intent, int startId) {
22 Message msg = mServiceHandler.obtainMessage();
23 msg.arg1 = startId;
24 msg.obj = intent;
25 mServiceHandler.sendMessage(msg);
26}
Copy the code
5.4 How Do I Determine the Time when IntentService Is Automatically Shut down?
In ServiceHandler, stopSelf(…) is actively called every time a task is executed. If the message queue is empty, the execution will continue. If the message queue is empty, the execution will continue.
1private final class ServiceHandler extends Handler {
2 public ServiceHandler(Looper looper) {
3 super(looper);
4 }
5 @Override
6 public void handleMessage(Message msg) {
7 onHandleIntent((Intent)msg.obj);
8 stopSelf(msg.arg1);
9 }
10}
Copy the code
The above are my views on IntentService, if you have any incorrect understanding, please correct me, learn together and make progress together. Thanks for reading, and I hope you found this article useful.
My name is Lin Chunfeng. I love reading. I am engaged in front-end development in a first-line large factory. Technology: Algorithms, Android Advanced Advanced, Java, Kotlin, Flutter growth management: Personal growth, self-improvement, reading notes, work awareness
Welcome to follow my official number: OAOAAce