在Android
的四大组件中,Service
排行老二,在Android
中的主要作用是后台服务,进行与界面无关的操作。由于Service
运行在主线程,所以进行异步操作需要在子线进行。为此Android
为我们提供了IntentService
。
IntentService
是一个抽象类,继承至Service
,主要方便我们新建工作线程进行异步操作。提交任务到IntentService
时,异步任务以串行方式进行处理,意味着工作线程一次只处理一个任务。而且当所有任务都完成之后,会自动停止Service
,不需要我们手动停止。
IntentService 的使用
- 我们定义
DownloadService
类并继承至IntentService
。来模拟网络下载的过程。
public class DownloadService extends IntentService {
private static int count = 0;
/**
* 主要用于调用服务类构造器
*
* @param name 用于区分不同任务
*/
public DownloadService(String name) {
super(name);
}
/**
* AndroidManifest.xml配置清单需要配置
*
* @param
*/
public DownloadService() {
super("action");
}
/**
*主要重写该方法,在该方法内进行异步操作。
**/
@Override
protected void onHandleIntent(Intent intent) {
Log.i("Download", "onHandleIntent" + count);
count++;
String name = intent.getStringExtra("action");
if (name.equals("download")) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
Log.i("Download", "download:" + count);
}
}
}
//以下方法的重写,仅仅为了打印日志
@Override
public void onDestroy() {
super.onDestroy();
Log.i("Download", "onDestroy");
}
@Override
public void onCreate() {
super.onCreate();
Log.i("Download", "onCreate");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i("Download", "onStart");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("Download", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
}
- 在AndroidManifest.xml配置
DownloadService
。
<service android:name=".DownloadService"/>
- 在MainActivity类中循环调用Service,启动多循环任务。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent=new Intent(this,DownloadService.class);
for (int i =0;i<3;i++){
intent.putExtra("action","download");
intent.putExtra("count",""+i);
startService(intent);
}
}
- 运行结果
分析:
从运行结果知道,IntentService
在运行多个任务情况下,只调用一次onCreate
,调用多次onStartCommand
,跟Service
的生命周期一致。但,只有在运行完download:1
之后才会去运行download:2
,接着是download:3
。最后所有任务结束后会自动调用onDestroy
,停止服务。在这里需要注意的是,和Service
并不同,Service
需要我们手动停止服务。对于结果的回调,可以采用接口回调,广播,EventBus
。
那么,IntentService
是如何在Service
中实现异步操作和串行处理任务的呢?
IntentService内部实现
- 查看IntentService的onCreate方法
@Override
public void onCreate() {
super.onCreate();
//分析一
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
分析二
mServiceHandler = new ServiceHandler(mServiceLooper);
}
分析一
HandThread
继承Thread
,通过start
方法创建工作线程,内部建立Looper
来达到消息循环,通过Hanlder
消息机制来达到串行的效果和处理多任务。HandThread
和Handler
消息机制,可以另外查看文章。
分析二
ServiceHandler
继承Handler
,与普通的Handler
并没有区别,在其内容处理handleMessage
。即调用IntentService
的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);
}
}
- 那么,当我们在
Activity
中重复调用startService
方法时,只会多次调用onStartCommand
方法,并不会重复调用onCreate
方法。我们看看onStartComamnd
方法的实现。
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
可以看得出,调用了onStart
方法了。而onStart方法只是将我们的Intent包装成Message,通过Handler发送出去,并在Handler中进行处理,调用我们的onHandleIntent
。进而调用我们实现onHandleIntent
的代码。
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
总结
IntentService
并没有什么的新的技术含量,在了解HandlerTread和Handler的消息机制下,对Handler+Thread+Service
作一个封装,更适合我们后台进行异步耗时操作的场景。有效避免通过new
多个Thread
。
网友评论