Androidintentservice full parse when service encounters handler
Reprint please indicate the source:
http://blog.csdn.net/lmj623565791/article/details/47143563;
This article is from: "Zhang Hongyang's Blog"
An overview
As we all know, in the development of Android, any time-consuming operation will be given to the service to do as much as possible, for example, we upload a number of images, upload process users may put the application in the background, and then do other things, our activity is likely to be killed, Therefore, you can consider the upload operation to the service to do, if you are worried about the service is killed, but also by setting startForeground(int, Notification)
the method to promote its priority.
Then, in the service we certainly can not directly take the time-consuming operation, generally need to open the sub-thread to do something, to manage the service life cycle and sub-threading is not an elegant approach; Fortunately, Android gives us a class, called IntentService
, Let's take a look at the note.
Intentservice is a base class for {@link service}s that handle asynchronous
Requests (expressed as {@link intent}s) on demand. Clients send requests
Through {@link android.content.context#startservice (Intent)} calls; The
Service is started as needed, handles each Intent in turn using a worker
Thread, and stops itself when the it runs out of the work.
Meaning that Intentservice is a service-based class that handles asynchronous requests. You can submit a request through StartService (Intent), which is created when needed, and shuts down after all tasks are completed, and the request is processed by the worker thread.
So, we use the Intentservice at least two benefits, on the one hand do not need to go to new thread, on the other hand do not need to consider when to shut down the service.
Well, then let's look at a complete example.
The use of two Intentservice
We will show a number of pictures upload case, of course, we will simulate the time-consuming upload, after all, our focus on the use of Intentservice and source resolution.
First Look at the
Whenever we click a button, a task is assigned to the service in the background, and the backend service completes a request to the activity, and then the activity updates the UI. When all tasks are completed, the backend service exits and does not occupy any memory.
Service
PackageCom.zhy.blogcodes.intentservice;ImportAndroid.app.IntentService;ImportAndroid.content.Context;ImportAndroid.content.Intent;ImportAndroid.util.Log; Public class uploadimgservice extends intentservice{ Private Static FinalString action_upload_img ="Com.zhy.blogcodes.intentservice.action.UPLOAD_IMAGE"; Public Static FinalString Extra_img_path ="Com.zhy.blogcodes.intentservice.extra.IMG_PATH"; Public Static void startuploadimg(context context, String path) {Intent Intent =NewIntent (context, uploadimgservice.class); Intent.setaction (ACTION_UPLOAD_IMG); Intent.putextra (Extra_img_path, PATH); Context.startservice (Intent); } Public Uploadimgservice() {Super("Uploadimgservice"); }@Override protected void onhandleintent(Intent Intent) {if(Intent! =NULL) {FinalString action = Intent.getaction ();if(Action_upload_img.equals (ACTION)) {FinalString path = Intent.getstringextra (Extra_img_path); Handleuploadimg (path); } } }Private void handleuploadimg(String Path) {Try{//Analog upload time-consumingThread.Sleep ( the); Intent Intent =NewIntent (Intentserviceactivity.upload_result); Intent.putextra (Extra_img_path, PATH); Sendbroadcast (Intent); }Catch(Interruptedexception e) {E.printstacktrace (); } }@Override Public void onCreate() {Super. OnCreate (); LOG.E ("TAG","OnCreate"); }@Override Public void OnDestroy() {Super. OnDestroy (); LOG.E ("TAG","OnDestroy"); }}
Code is very short, is mainly inherited IntentService
, and then the replication Onhandleintent method, according to the incoming intent to select the specific operation. startUploadImg
I wrote an auxiliary method, save every time to build Intent,startservice.
Activity
PackageCom.zhy.blogcodes.intentservice;ImportAndroid.content.BroadcastReceiver;ImportAndroid.content.Context;ImportAndroid.content.Intent;ImportAndroid.content.IntentFilter;ImportAndroid.os.Bundle;Importandroid.support.v7.app.AppCompatActivity;ImportAndroid.view.Menu;ImportAndroid.view.MenuItem;ImportAndroid.view.View;ImportAndroid.widget.LinearLayout;ImportAndroid.widget.TextView;ImportCOM.ZHY.BLOGCODES.R; Public class intentserviceactivity extends appcompatactivity{ Public Static FinalString Upload_result ="Com.zhy.blogcodes.intentservice.UPLOAD_RESULT";PrivateLinearLayout Mlytaskcontainer;PrivateBroadcastreceiver Uploadimgreceiver =NewBroadcastreceiver () {@Override Public void OnReceive(context context, Intent Intent) {if(intent.getaction () = = Upload_result) {String path = Intent.getstringextra (Uploadimgservice.extra_img_path); Handleresult (path); } } };Private void Handleresult(String Path) {TextView TV = (TextView) mlytaskcontainer.findviewwithtag (path); Tv.settext (path +"Upload Success ~ ~ ~"); }@Override protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); Setcontentview (R.layout.activity_intent_service); Mlytaskcontainer = (linearlayout) Findviewbyid (R.id.id_ll_taskcontainer); Registerreceiver (); }Private void Registerreceiver() {Intentfilter filter =NewIntentfilter (); Filter.addaction (Upload_result); Registerreceiver (uploadimgreceiver, filter); }inti =0; Public void AddTask(View view) {//Analog pathString Path ="/sdcard/imgs/"+ (++i) +". png"; Uploadimgservice.startuploadimg ( This, path); TextView TV =NewTextView ( This); Mlytaskcontainer.addview (TV); Tv.settext (path +"is uploading ..."); Tv.settag (path); }@Override protected void OnDestroy() {Super. OnDestroy (); Unregisterreceiver (Uploadimgreceiver); }}
activity, whenever I click on a button to call AddTask, back to the simulation to create a task, and then hand over to Intentservice to deal with.
Note that when each task of the service is completed, a broadcast is sent, and we register the broadcast separately in the activity's OnCreate and OnDestroy, and the specified UI is updated when the broadcast is received.
Layout file
<linearlayout android:id = "@+id/id_ll_taskcontainer" xmlns:android = "http://schemas.android.com/apk/res/android" xmlns:tools =" Http://schemas.android.com/tools " android:layout_width =" match_parent " android:layout_height =" match_parent " android:orientation =; <button android:layout_width="Wrap_content" android:layout_height= "Wrap_content" Android:onclick="AddTask" android:text="Add Task"/> </linearlayout>
OK, so that we have completed our needs, through the above example, you can see that we can use intentservice very convenient to handle background tasks, shielding a lot of details, and service and activity communication, we choose the way of broadcasting (of course, it can also use LocalBroadcastManager
).
After learning to use it, let's look at its internal implementation bang.
Three Intentservice source code analysis
Direct View Intentservice Source code
/* Copyright (C) The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "Licen Se "); * You are not a use this file except in compliance with the License. * Obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * unless required by appli Cable law or agreed into writing, software * Distributed under the License is distributed on a "as is" BASIS, * without Warranties or CONDITIONS of any KIND, either express OR implied. * See the License for the specific language governing permissions and * limitations under the License. */ PackageAndroid.app;ImportAndroid.content.Intent;ImportAndroid.os.Handler;ImportAndroid.os.HandlerThread;ImportAndroid.os.IBinder;ImportAndroid.os.Looper;ImportAndroid.os.Message; Public Abstract class intentservice extends Service { Private volatileLooper Mservicelooper;Private volatileServicehandler Mservicehandler;PrivateString Mname;Private BooleanMredelivery;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); } } Public Intentservice(String name) {Super(); Mname = name; } Public void Setintentredelivery(BooleanEnabled) {mredelivery = enabled; }@Override Public void onCreate() {Super. OnCreate (); Handlerthread thread =NewHandlerthread ("intentservice["+ Mname +"]"); Thread.Start (); Mservicelooper = Thread.getlooper (); Mservicehandler =NewServicehandler (Mservicelooper); }@Override Public void OnStart(Intent Intent,intStartid) {Message msg = Mservicehandler.obtainmessage (); MSG.ARG1 = Startid; Msg.obj = Intent; Mservicehandler.sendmessage (msg); }@Override Public int Onstartcommand(Intent Intent,intFlagsintStartid) {OnStart (intent, Startid);returnMredelivery? Start_redeliver_intent:start_not_sticky; }@Override Public void OnDestroy() {mservicelooper.quit (); }@Override PublicIBinderOnbind(Intent Intent) {return NULL; }protected Abstract void onhandleintent(Intent Intent);}
You can see that it initializes a handlerthread in the OnCreate, about the use of Handlerthread and the source code.
Analysis Reference: Android Handlerthread fully parse, see this estimate has been able to guess its logic:
Is that every time you call Onstartcommand, a message is sent through Mservicehandler that contains our intent. Then go back to onhandleintent (intent) in the handlemessage of the Mservicehandler;
Then we specifically look at the source code, sure enough, Onstartcommand callback in the Onstart,onstart in the Mservicehandler to send messages to the handler handlemessage. The last Handlemessage callback Onhandleintent (intent).
Note: Call Stopself (MSG.ARG1) back when the callback is complete, and note that this msg.arg1 is an int value, which is the equivalent of a request's unique identity. Each time a request is sent, a unique identity is generated, and then the request is placed in the queue when all execution is complete (the last request is the equivalent of Getlaststartid = = Startid), or the currently sent identity is the one recently issued (Getlaststartid = = Startid), our service will be destroyed.
If 1 is passed in, it is destroyed directly.
Then, when the task finishes destroying the service callback ondestory, you can see that our Looper:mServiceLooper.quit () is released in OnDestroy.
ok~ If you need to use Intentservice to do, you can use as much as possible, the design is still quite good. Of course, if you need to consider concurrency and so on, you may need to expand the thread pool yourself.
SOURCE Click to download
ok~~
Welcome to follow my Weibo http://weibo.com/u/3165018720
Group No.: 463081660, welcome into the group
Public Number: Hongyangandroid
(Welcome attention, the first time to push the blog post information)
Original link This article by Bean John Blog Backup expert remote One click release
Androidintentservice full parse when service encounters handler (reprint)