版权声明:本文出自汪磊的博客,转载请务必注明出处。
一、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。
本篇到此为止,希望对你有用。