/*** Create by SunnyDay /03/13 17:40:59*/
class DownLoadService : IntentService("FileDownLoadThread") {private val tag = "DownLoadService"override fun onHandleIntent(intent: Intent?) {Log.d(tag, "onHandleIntent Thread info: thread id -> ${Thread.currentThread().id} thread name -> ${Thread.currentThread().name}")Log.d(tag, "开始下载->")Log.d(tag, "下载ing...")SystemClock.sleep(3000)Log.d(tag, "下载完成")}override fun onCreate() {super.onCreate()Log.d(tag, "onCreate")}override fun onStart(intent: Intent?, startId: Int) {super.onStart(intent, startId)Log.d(tag, "onStart")}override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {Log.d(tag, "onStartCommand:startId->$startId")return super.onStartCommand(intent, flags, startId)}override fun onBind(intent: Intent?): IBinder? {Log.d(tag, "onBind")return super.onBind(intent)}override fun onUnbind(intent: Intent?): Boolean {Log.d(tag, "onUnbind")return super.onUnbind(intent)}override fun onDestroy() {super.onDestroy()Log.d(tag, "onDestroy")}
}
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)findViewById
//第一次开启 D/DownLoadService: onCreateD/DownLoadService: onStartCommand:startId->1D/DownLoadService: onStartD/DownLoadService: onHandleIntent Thread info: thread id -> 62 thread name -> IntentService[FileDownLoadThread]D/DownLoadService: 开始下载->D/DownLoadService: 下载ing...//第二次开启D/DownLoadService: onStartCommand:startId->2D/DownLoadService: onStartD/DownLoadService: 下载完成D/DownLoadService: onHandleIntent Thread info: thread id -> 62 thread name -> IntentService[FileDownLoadThread]D/DownLoadService: 开始下载->D/DownLoadService: 下载ing...D/DownLoadService: 下载完成D/DownLoadService: onDestroy
连续点击两次按钮,可以观察到log:
(1) IntentService的生命周期是这样的
onCreate -> onStartCommand -> onStart -> onHandleIntent -> onDestroy
(2) 系统默认帮我们开启一个子线程,我们可以在onHandleIntent中做一些耗时任务
(3) Service只会被创建一次,多次绑定onStartCommand回调多次
(4) 所有任务完成时onDestroy自动回调
在分析IntentService的源码之前我们需要了解一点东西~
之前总结过,可以看这里:参考
啥是handlerThread呢?其实就是官方封装的一个api方便我们进行"主线程发送消息,子线程处理消息",了解了handler的消息机制后我们可以尝试写下这个demo
(1)主线程发送消息,子线程处理消息demo
class HandlerThreadActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_handler_thread)// open a subThreadthread {Looper.prepare()val handler = Handler{when (it.what) {0x11 ->{Log.d("HandlerThreadActivity","${Thread.currentThread()}收到:${it.obj}")}}return@Handler true}runOnUiThread {Log.d("HandlerThreadActivity","${Thread.currentThread()}UI线程发送一条消息")// ui 线程发送消息handler.sendMessage(Message().apply {what = 0x11obj = "UI线程发送一条消息"})}Looper.loop()}}
}D/HandlerThreadActivity: Thread[main,5,main]UI线程发送一条消息D/HandlerThreadActivity: Thread[Thread-4,5,main]收到:UI线程发送一条消息
观察log发现我们实验成功了,其实不难理解主要是handler与Looper与Thread存在一定的绑定关系。接下来可以看下HandlerThread如何使用的。
(2)HandlerThread使用
/*** test:HandlerThread usage* */private fun test2() {// 1、创建对象,并开启线程val handlerThread = HandlerThread("HandlerThread")handlerThread.start()// 2、核心,使用两个参数的构造(这里的handleMessage 回调再子线程中的)val handler = Handler(handlerThread.looper) {// 处理消息return@Handler true}// 3、发送消息handler.sendEmptyMessage(0x11)}
借助系统的api就快速了不少,我们可以很方便实现"主线程发送消息,子线程处理消息",接下来看看源码实现。
(3)HandlerThread源码
// 1、首先HandlerThread是一个普通的线程,只是这个线程绑定可Looper(持有Looper成员变成)
public class HandlerThread extends Thread {int mPriority;int mTid = -1;Looper mLooper;// 构造传递的是线程名字public HandlerThread(String name) {super(name);mPriority = Process.THREAD_PRIORITY_DEFAULT;}public HandlerThread(String name, int priority) {super(name);mPriority = priority;}protected void onLooperPrepared() {}// 2、run方法内部进行了实现,核心有两步:// (1) 创建Looper对象// (2) 开启Loop轮训@Overridepublic void run() {mTid = Process.myTid();Looper.prepare();synchronized (this) {mLooper = Looper.myLooper();notifyAll();}Process.setThreadPriority(mPriority);onLooperPrepared();Looper.loop();mTid = -1;}// 3、提供了getLooper、getThreadHandler来获取对应的对象public Looper getLooper() {if (!isAlive()) {return null;}boolean wasInterrupted = false;// If the thread has been started, wait until the looper has been created.synchronized (this) {while (isAlive() && mLooper == null) {try {wait();} catch (InterruptedException e) {wasInterrupted = true;}}}if (wasInterrupted) {Thread.currentThread().interrupt();}return mLooper;}@NonNullpublic Handler getThreadHandler() {if (mHandler == null) {mHandler = new Handler(getLooper());}return mHandler;}}
可以看到实现十分简单,只要明白handler的消息机制这个还是很好明白的。
public abstract class IntentService extends Service {
// 1、定义个Looper类型的成员变量(注意这个Looper绑定的线程为HandlerThread工作线程,这就意味着消息的处理是在工作线程)private volatile Looper mServiceLooper;private volatile ServiceHandler mServiceHandler;private String mName;private boolean mRedelivery;//2、定义个Handler,这个handler的handleMessage回调在工作线程(Looper绑定的为工作线程)private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}@Overridepublic 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;}@Overridepublic void onCreate() {super.onCreate();//3、创建HandlerThread并绑定LooperHandlerThread thread = new HandlerThread("IntentService[" + mName + "]");thread.start();mServiceLooper = thread.getLooper();mServiceHandler = new ServiceHandler(mServiceLooper);}@Overridepublic void onStart(@Nullable Intent intent, int startId) {Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;msg.obj = intent;mServiceHandler.sendMessage(msg);}@Overridepublic int onStartCommand(@Nullable Intent intent, int flags, int startId) {onStart(intent, startId);return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;}@Overridepublic void onDestroy() {mServiceLooper.quit();}// 这里需要注意 方法默认返回为空。从源码也可看出无bindService@Override@Nullablepublic IBinder onBind(Intent intent) {return null;}protected abstract void onHandleIntent(@Nullable Intent intent);
}
JobIntentService
官方文档
活儿好又不纠缠的IntentService
Android IntentService详解(源码分析)