Android异步加载全解析之IntentService
搞什么IntentService
前面我们说了那么多,异步处理都使用钦定的AsyncTask,再不济也使用的Thread,那么这个IntentService是个什么鬼。
相对与前面我们提到的这两种异步加载的方式来说,IntentService有一个最大的特点,就是——IntentService不受大部分UI生命周期的影响,它为后台线程提供了一个更直接的操作方式。不过,IntentService的不足主要体现在以下几点:
- 不可以直接和UI做交互。为了把他执行的结果体现在UI上,需要发送给Activity。
- 工作任务队列是顺序执行的,如果一个任务正在IntentService中执行,此时你再发送一个任务请求,这个任务会一直等待直到前面一个任务执行完毕。
- 正在执行的任务无法打断。
创建IntentService
当我们创建一个类并继承IntentService后,通过IDE的提示,我们基本可以生成如下所示的代码:
package com.imooc.intentservicetest; import android.app.IntentService; import android.content.Intent; public class MyIntentService extends IntentService { /** * Creates an IntentService. Invoked by your subclass's constructor. * * @param name Used to name the worker thread, important only for debugging. */ public MyIntentService(String name) { super(name); } public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(Intent intent) { } }
PS:需要注意的是,系统会提示我们生成一个带参数的构造方法,另外,我们还需要定义一个无参数的构造方法,并调用一个参数的构造方法。所以,一个带参数的构造方法其实是可以删掉的。
最重要的就是:
@Override protected void onHandleIntent(Intent intent) { }
在这个方法里面,我们从intent中获取数据,并进行相应的操作。
ps:IntentService继承自Service,但是我们不需要手动调用onStartCommand()等Service回调方法。
申明IntentService
我们需要在Mainifest文件中对IntentService进行申明:
<service android:name=".MyIntentService" android:exported="false"/>
与申明一个Service类似,但是却不需要申明<intent-filter>,因为发送任务给IntentService的Activity需要使用显式Intent,所以不需要filter。这也意味着只有在同一个app或者其他使用同一个UserID的组件才能够访问到这个IntentService。
启动IntentService
启动IntentService与启动Service基本类似,而且我们可以在Intent中传入相关的参数。例如:
package com.imooc.intentservicetest; import android.app.Activity; import android.content.Intent; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = null; for (int i = 0; i < 10; i++) { intent = new Intent(this, MyIntentService.class); intent.putExtra("xys", "" + i); startService(intent); } } }
可以看见,我们start了10个IntentService,最后执行的结果如下:
05-13 17:14:53.515 19991-20011/com.imooc.intentservicetest D/xys﹕ onHandleIntent0 05-13 17:14:55.528 19991-20011/com.imooc.intentservicetest D/xys﹕ onHandleIntent1 05-13 17:14:57.540 19991-20011/com.imooc.intentservicetest D/xys﹕ onHandleIntent2 05-13 17:14:59.544 19991-20011/com.imooc.intentservicetest D/xys﹕ onHandleIntent3 05-13 17:15:01.556 19991-20011/com.imooc.intentservicetest D/xys﹕ onHandleIntent4 05-13 17:15:03.569 19991-20011/com.imooc.intentservicetest D/xys﹕ onHandleIntent5 05-13 17:15:05.570 19991-20011/com.imooc.intentservicetest D/xys﹕ onHandleIntent6 05-13 17:15:07.574 19991-20011/com.imooc.intentservicetest D/xys﹕ onHandleIntent7 05-13 17:15:09.577 19991-20011/com.imooc.intentservicetest D/xys﹕ onHandleIntent8 05-13 17:15:11.581 19991-20011/com.imooc.intentservicetest D/xys﹕ onHandleIntent9
所以说,启动IntentService之后,它将默认生成一个Worker Thread,并将这些IntentService依次放入队列,每次取出一个进行执行,当执行完毕后,这个IntentService会自动stop自己,当所有intent都执行完毕后,服务就结束了,不需要自己手动来结束。
IntentService修改UI
IntentService如果要进行UI的修改,那么只能通过Handler来实现,或者使用广播机制来通知修改UI。
IntentService与AsyncTask的区别
- 对于异步更新UI来说,IntentService使用的是Serivce+handler或者广播的方式,而AsyncTask是thread+handler的方式。
- AsyncTask比IntentService更加轻量级一点。
- Thread的运行独立于Activity,当Activity结束之后,如果没有结束thread,那么这个Activity将不再持有该thread的引用。
- Service不能在onStart方法中执行耗时操作,只能放在子线程中进行处理,当有新的intent请求过来都会线onStartCommond将其入队列,当第一个耗时操作结束后,就会处理下一个耗时操作(此时调用onHandleIntent),都执行完了自动执行onDestory销毁IntengService服务。
代码地址:戳我戳我