上一章我们学习了HandlerThread,这一章我们来认识一下Android多线程通信常用的最后一个类IntentService。顾名思义,IntentService是一个Service的子类,其本质还是一个服务,不过它与它的父类还是有一些区别的,下面我们就来详细讲一下。
IntentService的使用十分简单,分为下面几个步骤:
新建IntentService子类,并复写onHandleIntent方法:
/**
* 工作线程执行,其原理还是Handler,详细细节见源码
* @param intent
*/
@WorkerThread
@Override
protected void onHandleIntent(@Nullable Intent intent) {
Bundle bundle = intent.getExtras();
String fileName = bundle.getString("file_name");
Log.e(TAG,"当前下载"+fileName+"当前线程id"+Thread.currentThread().getId());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Intent resultIntent = new Intent(DOWNLOAD_FINISH);
resultIntent.putExtras(bundle);
LocalBroadcastManager.getInstance(this).sendBroadcast(resultIntent);
}
Activity启动service
//启动两次,但是顺序执行,第一个任务执行完毕才会执行第二个任务的操作
public void onClick(View view) {
Intent intent = new Intent(this,DownLoadIntentService.class);
Bundle bundle = new Bundle();
bundle.putString("file_name","巴啦啦小魔仙.mp4");
intent.putExtras(bundle);
startService(intent);
Intent intent2 = new Intent(this,DownLoadIntentService.class);
Bundle bundle2 = new Bundle();
bundle2.putString("file_name","金刚葫芦娃.mp4");
intent2.putExtras(bundle2);
startService(intent2);
}
使用本地广播传递给主线程
Intent resultIntent = new Intent(DOWNLOAD_FINISH);
resultIntent.putExtras(bundle);
LocalBroadcastManager.getInstance(this).sendBroadcast(resultIntent);
Activity获取结果并进行相应处理
intentFilter = new IntentFilter(DownLoadIntentService.DOWNLOAD_FINISH);
receiver = new DownLoadBroadcastReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(receiver,intentFilter);
private class DownLoadBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(TextUtils.equals(intent.getAction(),DownLoadIntentService.DOWNLOAD_FINISH)) {
Bundle bundle = intent.getExtras();
String fileName = bundle.getString("file_name");
String result = tvResult.getText().toString();
result += "名为"+fileName+"的文件下载完成!\r";
tvResult.setText(result);
Toast.makeText(IntentServiceDemoActivity.this,"下载完成,当前下载文件名"+fileName,Toast.LENGTH_SHORT).show();
}
}
}
这里我使用的本地广播进行消息的传递。
我们打开IntentService 的源码来分析其实现原理。
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;//子线程绑定的Looper
private volatile ServiceHandler mServiceHandler;//HandlerThread实例
private String mName;//传入的参数,默认缺省
private boolean mRedelivery;
/** 绑定工作线程Handler,handleMessage运行于子线程中 **/
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实例并启动这个线程
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
//将HandlerThread中的Looper与该Service 绑定,并新建子线程Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
//调用startService后调用onStartCommand并转到该方法中
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
//发出消息,arg1带上自身ID,使其完成时关闭自身
}
//如果系统在服务完成之前关闭Service,START_NOT_STICKY型服务会直接被关闭,而START_REDELIVER_INTENT 型服务会在可用资源不再吃紧的时候尝试再次启动服务。
@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() {
//Looper退出循环
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
//默认返回null
return null;
}
/** 子线程中运行,在Handler的handleMessage中调用此方法 **/
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
可以看到将注释删除后也就只有短短100行。具体的分析可以体现为:
调用startService() -> onCreate()被调用,绑定一个HandlerThread到当前Service,并生成一个子线程Handler -> onStartCommand()被调用 -> 最终调用onStart(@Nullable Intent intent, int startId) 方法并发送消息给消息循环 -> 其余就是Handler的处理消息过程,最终调用onHandleIntent并在执行完毕后调用stopSelf关闭自身。
这章的内容就是这样,如果文章内容出现错误或者偏差,希望您能联系我,我会尽快进行更改。
demo地址
我的个人博客,欢迎来访~
感谢阅读~