一、问题引入
Android代码设计中耗时的IO操作会放置在Service中进行执行,但是由于Service也是运行在主线程中,因此在设计中会在Service开一个线程来完成耗时IO操作的业务部分。线程一般会放置在Service的onStartCommand函数中执行。
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// 处理具体的逻辑
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
}
Service在被startService启动调用之后,需要使用stopService来停在service,否则service可能会一直运行下去。因此需要我们在线程结束的代码中添加stopself,让service自动停止下来销毁掉。
new Thread(new Runnable() {
@Override
public void run() {
// 处理具体的逻辑
stopSelf(); //补充停止服务的逻辑
}
}).start();
由于需要自定义线程,并且需要在线程结束之后还记得写上stopSelf代码,因此《Android开发手册.pdf》并不推荐采用上述方式在service中完成耗时操作,而是建议采用IntentService来完成上述要求的业务逻辑。
二、IntentService的使用介绍
关于IntentService的介绍网上有很多,可以归纳总结为如下几点:
1.IntentService继承自Service,启动IntentService的方式和启动传统Service一样。
2.IntentService内有一个工作线程来处理耗时的操作,当任务执行完成后,IntentService会自动停止。
3.可以启动IntentService多次,每一个耗时的操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,每次只会执行一个工作线程,执行完第一个再执行第二个,依次类推。
使用代码范例
在AndroidManifest.xml代码中添加IntentService的继承代码MyIntentService。
<service android:name=".MyIntentService"></service>
MyIntentService的代码实现
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
/**
* Created by moxie on 2018/6/26.
*/
public class MyIntentService extends IntentService {
public static final String TAG = MyIntentService.class.getSimpleName();
public static final String EXTRA_KEY = "task_name";
public MyIntentService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
String value = intent.getStringExtra(EXTRA_KEY);
if (value.contains("two")) {
try {
// 如果是第二个任务,则sleep三秒。
// 发现第三个任务仍然在第二个任务之后执行,说明任务是串行执行的
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.e(TAG, "thread : " + Thread.currentThread().getName() + " " + value);
}
@Override
public void onDestroy() {
super.onDestroy();
// 服务结束时,打印Log
Log.e(TAG, "onDestroy");
}
}
在Activity中调用IntentService
Intent intent = new Intent(this, MyIntentService.class);
intent.putExtra(MyIntentService.EXTRA_KEY, "my task one #");
// 发送任务1
startService(intent);
intent.putExtra(MyIntentService.EXTRA_KEY, "my task two #");
// 发送任务2
startService(intent);
intent.putExtra(MyIntentService.EXTRA_KEY, "my task three #");
// 发送任务3
startService(intent);
结果输出
从结果中可以看出通过IntentService执行的任务是依次执行的。
三、IntentService的源码解析
IntentService的源码如下
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
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);
}
}
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
从上面IntentService的源码中可以看到如下几点:
1.IntentService通过HandlerThread创建了一个非UI线程的Looper。
2.通过非UI线程的Looper创建了一个Handler的继承类ServiceHandler的对象。
3.在onStart函数中,将通过调用startService服务过来的intent都发送到ServiceHandler中去执行,子类会实现onHandleIntent函数,子类在该函数中完成复杂的耗时任务。
4.添加停止服务的stopself函数,保证任务结束后自行停止服务。
由于Handler内部是有一个MessageQueue队列的,因此我们能够在上述的范例中看到,IntentService会顺序执行用户调用的服务。
IntentService的逻辑流程如下:
参考链接
https://blog.csdn.net/lyj1005353553/article/details/53647121
https://www.cnblogs.com/zgqys1980/p/5478668.html
https://www.jianshu.com/p/8a3c44a9173a
https://blog.csdn.net/VNanyesheshou/article/details/75125909
https://blog.csdn.net/a740169405/article/details/50274537
https://blog.csdn.net/javazejian/article/details/52709857