1.简单使用
tv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(HandleActivity.this, MyIntentService.class);
intent.putExtra("name", "jj");
intent.putExtra("age", 15);
startService(intent);
}
});
public class MyIntentService extends IntentService {
public static final String TAG = "MyIntentService";
public MyIntentService() {
super(TAG);
Log.d(TAG, "MyIntentService() is invoke "+Thread.currentThread().getId()+"="+Thread.currentThread().getName());
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate is invoke "+Thread.currentThread().getId()+"="+Thread.currentThread().getName());
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand is invoke "+Thread.currentThread().getId()+"="+Thread.currentThread().getName());
return super.onStartCommand(intent, flags, startId);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
//做耗时操作
Log.d(TAG, "onHandleIntent is invoke "+Thread.currentThread().getId()+"="+Thread.currentThread().getName());
int age = intent.getIntExtra("age",0);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "age = "+age);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy is invoke "+Thread.currentThread().getId()+"="+Thread.currentThread().getName());
}
}
运行后的日志:
2019-03-12 14:03:09.138 18881-18881/com.ysl.myandroidbaseserver D/MyIntentService: MyIntentService() is invoke 2=main
2019-03-12 14:03:09.141 18881-18881/com.ysl.myandroidbaseserver D/MyIntentService: onCreate is invoke 2=main
2019-03-12 14:03:09.142 18881-18881/com.ysl.myandroidbaseserver D/MyIntentService: onStartCommand is invoke 2=main
2019-03-12 14:03:09.143 18881-18918/com.ysl.myandroidbaseserver D/MyIntentService: onHandleIntent is invoke 3270=IntentService[MyIntentService]
2019-03-12 14:03:19.144 18881-18918/com.ysl.myandroidbaseserver D/MyIntentService: age = 15
2019-03-12 14:03:19.148 18881-18881/com.ysl.myandroidbaseserver D/MyIntentService: onDestroy is invoke 2=main
可以看到它可以执行一个耗时任务在我们重写的onHandleIntent方法中;其它的几个方法因为它继承自service,所以都在主线程中进行;service中不能执行耗时任务,否则就会ANR;但是IntentService却可以,那它是怎么做到的呢?
2.看看IntentService的源码
首先开启一个服务会调用onCreate方法,我们看看它的onCreate方法干了什么
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
可以发现onCreate中使用了HandlerThread;并且把HandlerThread的looper传递给ServiceHandler;
我们再来看看ServiceHandler:
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);
}
}
果然它是一个内部类,里面重写了handleMessage方法,并且调用了我们重写的onHandleIntent((Intent)msg.obj);其实我们就是在这个方法中做的耗时任务。所以IntentService使用的还是handler机制,把任务从主线程挪到了子线程去执行了。并且执行完任务后,有调用了stopSelf(msg.arg1)方法;把服务停止了。
接下来看onStartCommand:
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
调用了onStart(intent, startId);把intent继续向下传递了;
接着看onStart方法:
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
这段代码就很熟悉了,构建了一个message对象,并把intent和startid包装好,发送了handler消息;这里就是我们上边分析的ServiceHandler;然后就在handleMessage中把intent传给了onHandleIntent((Intent)msg.obj);最后执行完任务把服务停止。
在onDestroy中调用:mServiceLooper.quit();把looper也退出了。
3.总结
IntentService其实内部使用的是:HandlerThread中的looper创建的一个ServiceHandler;通过ServiceHandler把intent发送到子线程进行处理业务。从而实现在service所在的主线程中把任务发送到子线程HandlerThread中进行处理。
IntentService会在任务执行完成后自行结束自己,而不需要外部去调用stopService了。