1、简述
由于Service作为四大组件之一,其运行在主线程中,无法执行耗时操作,通过如果需要执行耗时操作需要创建线程来执行异步任务,但其实不用自己创建线程,安卓原生中提供了一种类:IntentService。
其是一种继承自Service的异步请求类。
2、简单使用
public class TestIntentService extends IntentService {
private static final String TAG = "TestIntentService";
/**
* Creates an IntentService. Invoked by your subclass's constructor.
* name Used to name the worker thread, important only for debugging.
*/
public TestIntentService() {
super("xiaohan");
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: ");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.i(TAG, "onHandleIntent: " + intent.getIntExtra("progress", 0));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: " + intent.getIntExtra("progress", 0));
return super.onStartCommand(intent, flags, startId);
}
}
//通过startService开启
Intent intent = new Intent(MainActivity.this, TestIntentService.class);
for (int i = 1; i < 6; i++) {
intent.putExtra("progress", i);
startService(intent);
}
简要说明:
- 重写构造方法:和普通的Service不同,IntentService 需要提供重写构造方法,并在super()中添加字符串,查看源码可以发现,该字符串用于定义HandlerIntent的线程名称;
- 重写onHandleIntent:该方法用于执行异步的耗时操作;
- 不强制重写onBind方法:普通的Service必须要重写onBind,而IntentService 内部对其做了重写处理
3、源码分析
IntentService 的源码分析可以从其三个方法:onCreate()、onStartCommand()和onHandleIntent()入手分析。
3.1 onCreate()
IntentService 再怎么封装,其本质上还是一个Service,因此其最先执行的还是onCreate方法。
//IntentService
@Override
public void onCreate() {
super.onCreate();
//1、创建并启动HandlerThread 类
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
//2、获取HandlerThread 中的Looper对象
mServiceLooper = thread.getLooper();
//3、将HandlerThread的Looper对象与工作区的ServiceHandler相绑定
mServiceHandler = new ServiceHandler(mServiceLooper);
}
简要说明:
- 创建HandlerThread类:在IntentService 想要执行异步的操作,必须要有线程的消耗,在Android的HandlerThread的源码分析中分析到HandlerThread是一种轻量的异步处理类,并且其内部嵌套了Handler和Looper,方便调用;
- 创建ServiceHandler类:其实该类就是继承自Handler并重写handleMessage的自定义类,主要作用是异步的耗时操作。
以上是为了线程的异步操作了做了充分准备。
3.2 onStartCommand()
同样在调用startService时,也必然会调用onStartCommand方法。
//IntentService
//1、重写onStartCommand,调用onStart方法
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
//2、发送intent信息至ServiceHandler
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
//3、接收到ServiceHandler发送的处理任务后,将Intent传至onHandleIntent中,而onHandleIntent是用户重写的异步处理的方法
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);
}
}
简要说明:
- 请求异步操作:创建Intent,将需要执行异步任务的参数,调用startService发送至异步线程中并启动Service;
- 发送过程:Service启动后,通过onStartCommand()–onStart()–ServiceHandler 传递至handleMessage中,而handleMessage又将Intent传递至onHandleIntent中,重写onHandleIntent后,就可以获取异步任务的参数。
- 结束任务:在handleMessage中存在stopSelf(msg.arg1)方法,并且该方法是包含有参数的,而包含参数的stopSelf是线程安全的,因此只有所有的消息任务执行完成后,才会终止该线程流程。
3.3 onHandleIntent()
在3.2中已经了解,最终的异步请求的参数会传至onHandleIntent()中(当然onStartCommand()也可以收到),在3.1中了解ServiceHandler 其实是与异步类HandlerThread 相绑定的,因此onHandleIntent()就是我们执行异步操作的方法,在该方法中我们可以根据需要,执行耗时操作。
@Override
protected void onHandleIntent(Intent intent) {
Log.i(TAG, "onHandleIntent: " + intent.getIntExtra("progress", 0));
SystemClock.sleep(10*1000);
minterface .updateUI("result");
}
public interface UpdateUI{
void updateUI(String result );
}
在异步任务完成后,可通过接口回调的形式返回值UI线程中。