Android IntentService使用介绍以及源码解析

版权声明:本文出自汪磊的博客,转载请务必注明出处。

一、IntentService概述及使用举例

IntentService内部实现机制用到了HandlerThread,如果对HandlerThread不了解的话建议先看上篇文章:Android HandlerThread使用介绍以及源码解析

IntentService是神马玩意?它就是一个Service,但是我们知道在Service中不能进行耗时操作,如果要进行耗时操作的话我们就需要自己new一个子线程在里面进行耗时操作,然而这一切谷歌工程师早就替我们做好了,只需使用IntentService即可,自己会启动一个子线程做耗时操作,无需我们自己管理子线程,并且完成任务后会自动停止。这么好的玩意赶紧看下怎么使用。

接下来我们编写一个小Demo,模拟在IntentService中进行网络通信,并且成功后通知主线程,主线程做出相应反应。Demo中通过广播接收者实现子线程与主线程的通信。

首先我们编写IntentService,如下:

 1 public class MyIntentService extends IntentService {
 2 
 3     public static final String TAG = "WL";
 4 
 5     public MyIntentService() {
 6         //为子线程起一个名字
 7         super("IntentService");
 8         
 9     }
10 
11     //子线程中执行
12     @Override
13     protected void onHandleIntent(Intent intent) {
14         // TODO Auto-generated method stub
15         if(null !=intent){
16             String action = intent.getAction();
17             if(action.equalsIgnoreCase(MainActivity.ACTION_START)){
18                 
19                 String url = intent.getStringExtra(MainActivity.URL);
20                 Log.i(TAG, "开始请求_URL:"+url);
21                 //模拟网络请求
22                 try {
23                     Thread.sleep(2000);
24                 } catch (InterruptedException e) {
25                     // TODO Auto-generated catch block
26                     e.printStackTrace();
27                 }
28                 Log.i(TAG, "请求成功");
29                 //
30                 handlerRequestSuccess();
31             }
32         }
33     }
34 
35     //
36     private void handlerRequestSuccess() {
37         // 发送广播通知主线程请求成功
38         Intent intent = new Intent(MainActivity.ACTION_START);
39         intent.putExtra("msg", "请求成功");
40         sendBroadcast(intent);
41     }
42     
43 }

主要逻辑就是继承IntentService,重写onHandleIntent方法,onHandleIntent运行在子线程可以进行耗时操作,在模拟网络请求成功的时候发送广播。

接下来看下MainActivity逻辑:

 1 public class MainActivity extends Activity {
 2 
 3     //
 4     public static final String ACTION_START= "START_HTTP_REQUEST";
 5     public static final String URL= "URL";
 6     private MyBroadcastReceiver myBroadcastReceiver;
 7 
 8     @Override
 9     protected void onCreate(Bundle savedInstanceState) {
10         super.onCreate(savedInstanceState);
11         setContentView(R.layout.activity_main);
12         //注册广播接收者
13         myBroadcastReceiver = new MyBroadcastReceiver();
14         IntentFilter filter = new IntentFilter();
15         filter.addAction(ACTION_START);
16         registerReceiver(myBroadcastReceiver, filter);
17     }
18     
19     @Override
20     protected void onResume() {
21         //
22         super.onResume();
23         Intent intent = new Intent(this, MyIntentService.class);
24        intent.setAction(ACTION_START);
25         intent.putExtra(URL, "http://www.cnblogs.com/leipDao/");
26        startService(intent);//必须是start方式启动服务,bind方法无效,分析源码的时候就明白了
27     }
28     
29     @Override
30     protected void onDestroy() {
31         // TODO Auto-generated method stub
32         super.onDestroy();
33         unregisterReceiver(myBroadcastReceiver);
34     }
35     
36     private class MyBroadcastReceiver extends BroadcastReceiver {
37 
38         @Override
39         public void onReceive(Context context, Intent intent) {
40             
41             String action = intent.getAction();
42             if(action.equalsIgnoreCase(ACTION_START)){
43                 
44                 String extra = intent.getStringExtra("msg");
45                 Log.i(MyIntentService.TAG, "onReceive::::"+extra);
46             }
47         }
48     }
49 }

逻辑也是比较简单,onCreate的时候注册广播接收者,用于接收IntentService中模拟网络请求成功的时候发送的广播,onResume的时候启动服务。onDestroy的时候移除广播接收者。Demo比较简单,运行程序打印如下:

 

IntentService中完成耗时操作并且完成子线程与主线程的通信。

二、IntentService源码解析

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 
 7     private final class ServiceHandler extends Handler {
 8         public ServiceHandler(Looper looper) {
 9             super(looper);
10         }
11 
12         @Override
13         public void handleMessage(Message msg) {
14             onHandleIntent((Intent)msg.obj);
15             stopSelf(msg.arg1);
16         }
17     }
18 
19     /**
20      * Creates an IntentService.  Invoked by your subclass's constructor.
21      *
22      * @param name Used to name the worker thread, important only for debugging.
23      */
24     public IntentService(String name) {
25         super();
26         mName = name;
27     }
28 
29     public void setIntentRedelivery(boolean enabled) {
30         mRedelivery = enabled;
31     }
32 
33     @Override
34     public void onCreate() {
35         // TODO: It would be nice to have an option to hold a partial wakelock
36         // during processing, and to have a static startService(Context, Intent)
37         // method that would launch the service & hand off a wakelock.
38 
39         super.onCreate();
40         HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
41         thread.start();
42 
43         mServiceLooper = thread.getLooper();
44         mServiceHandler = new ServiceHandler(mServiceLooper);
45     }
46 
47     @Override
48     public void onStart(Intent intent, int startId) {
49         Message msg = mServiceHandler.obtainMessage();
50         msg.arg1 = startId;
51         msg.obj = intent;
52         mServiceHandler.sendMessage(msg);
53     }
54 
55     /**
56      * You should not override this method for your IntentService. Instead,
57      * override {@link #onHandleIntent}, which the system calls when the IntentService
58      * receives a start request.
59      * @see android.app.Service#onStartCommand
60      */
61     @Override
62     public int onStartCommand(Intent intent, int flags, int startId) {
63         onStart(intent, startId);
64         return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
65     }
66 
67     @Override
68     public void onDestroy() {
69         mServiceLooper.quit();
70     }
71 
72     @Override
73     public IBinder onBind(Intent intent) {
74         return null;
75     }
76 
77     @WorkerThread
78     protected abstract void onHandleIntent(Intent intent);
79 }

很简短吧,出去注释不到100行,接下来我们分析重点部分。

24-27行,构造函数传递进来一个name,用于第40行初始化HandlerThread,就是子线程的名字。

接下来看34-45行onCreate()的时候:主要就是初始化一个HandlerThread以及ServiceHandler,7-17行发现ServiceHandler就是一个普通的Handler而已。看过上一篇Android HandlerThread使用介绍以及源码解析应该明白,ServiceHandler运行在子线程中,这里就不仔细解释了,不明白的地方可以查看Android HandlerThread使用介绍以及源码解析

73-75行发现onBind的时候什么也没做,就是返回null,还记得demo中注释吗必须以start方式启动服务,因为bing方式启动什么也没做。

48-53行onStart的时候发送一个消息到ServiceHandler,第14行handleMessage的时候直接调用onHandleIntent方法,紧接着15行结束本次任务。

到这里主要流程就完了,其本质就是利用了HandlerThread保证ServiceHandler在子线程运行机制,在我们以start方式启动服务的时候,执行到service生命周期方法onStart的时候就会发送一个消息,然后在ServiceHandler中handleMessage方法执行onHandleIntent方法,子类重写此方法实现耗时任务即可。

好了,到此IntentService就分析完了,理解IntentService最核心的就是先理解HandlerThread。

本篇到此为止,希望对你有用。

posted @ 2017-12-15 09:46  WangLei_ClearHeart  阅读(1376)  评论(0编辑  收藏  举报