美文网首页Android开发Android源码分析Android技术知识
Android源码系列二:HandlerThread和Inten

Android源码系列二:HandlerThread和Inten

作者: Taonce | 来源:发表于2019-05-27 09:01 被阅读5次

    在分析了 Handler源码 之后,我们紧接着加入了相关联的 HandlerThreadIntentService 的源码剖析。

    HandlerThread

    它是 Thread 的子类,并且自带 Looper 光环

    1. 如何使用:
          // 创建 HandlerThread 对象
          val handlerThread = HandlerThread("mainActivity")
          handlerThread.start()
          // 获取 HandlerThread 中的 Looper 对象
          val myLooper: Looper = handlerThread.looper
          val handler = object : Handler(myLooper) {
              override fun handleMessage(msg: Message?) {
                  // 运行在 HandlerThread 线程中
                  super.handleMessage(msg)
                  Log.d("taonce", "handleMessage thread is: ${Thread.currentThread().name}")
                  Log.d("taonce", "handleMessage msg is: ${msg?.arg1}")
              }
          }
          val message: Message = handler.obtainMessage()
          message.arg1 = 0x11
          // 主线程中发送消息
          handler.sendMessage(message)
          thread {
              val msg: Message = handler.obtainMessage()
              msg.arg1 = 0x01
              // 子线程中发送消息
              handler.sendMessage(msg)
          }
          
      // Log:
      // handleMessage thread is: mainActivity
      // handleMessage msg is: 17
      // handleMessage thread is: mainActivity
      // handleMessage msg is: 1
      
      通过 Log 可以发现,无论我们在子线程中还是主线程中发送消息,handlerMessage(msg) 都是运行在 handlerThread 中。而且,将 handlerThread 中的 Looper 传递给 handler 后,handler 也不需要再进行 Looper.prepare()Looper.loop() 的执行过程了,最终 handlerhandleMessage(msg: Message?) 也会在 handlerThread 中进行。
      也就是说:HandlerThread 开启了一个线程来实现多线程效果,但是它处理多任务是按照串行执行。
    2. 源码简析:
      @Override
      public void run() {
          mTid = Process.myTid(); 
          Looper.prepare();
          synchronized (this) {
              mLooper = Looper.myLooper();
              notifyAll();
          }
          Process.setThreadPriority(mPriority);
          onLooperPrepared();
          Looper.loop();
          mTid = -1;
      }
      
      源码的 run() 方法中就是把我们在子线程中需要做的默认做了一遍,以免造成在子线程中使用 Handler.sendMessage(msg: Message?) 造成 No Looper 的异常。

    IntentService

    1. 如何使用:

      class MyIntentService : IntentService("") {
          override fun onHandleIntent(intent: Intent?) {
          // 让此线程休眠一会
           Thread.sleep(60 * 1000 * 1000)
          }
      
          override fun onStart(intent: Intent?, startId: Int) {
           super.onStart(intent, startId)
        }
      
          override fun onCreate() {
              super.onCreate()
       }
      }
      

      在我们使用 Service 的时候,都知道 Service 是运行在主线程中,不可以做耗时操作,但是我们在 IntentServiceonHandleIntent(intent: Intent?) 将线程休眠都没有出现ANR,是不是很疑惑,下面我们就看看 IntentService 的源码是怎么处理的。

    2. 源码简析:

      // 我将一些未参与分析的源码都给删除了,只保留了和 HandlerThread 相关的
      public abstract class IntentService extends Service {
          // HandlerThread 中的 Looper 对象
          private volatile Looper mServiceLooper;
          // Handler 对象
          private volatile ServiceHandler mServiceHandler;
      
      
          private final class ServiceHandler extends Handler {
              public ServiceHandler(Looper looper) {
                  super(looper);
              }
      
              @Override
              public void handleMessage(Message msg) {
                  // 将子线程的处理交给抽象方法:onHandleIntent(@Nullable Intent intent)
                  onHandleIntent((Intent)msg.obj);
                  stopSelf(msg.arg1);
              }
          }
      
          @Override
          public void onCreate() {
      
              super.onCreate();
              // 创建 HandlerThread 对象,并开启此线程
              HandlerThread thread = new HandlerThread("IntentService[" + mName +     "]");
              thread.start();
              // 获取子线程中的 Looper 对象
              mServiceLooper = thread.getLooper();
              // 将 Looper 传递给 ServiceHandler
              mServiceHandler = new ServiceHandler(mServiceLooper);
          }
          
              @Override
          public void onStart(@Nullable Intent intent, int startId) {
              Message msg = mServiceHandler.obtainMessage();
              msg.arg1 = startId;
              msg.obj = intent;
              // 发送消息,然后在 handleMessage(Message msg) 处理
              mServiceHandler.sendMessage(msg);
          }
          
          @WorkerThread
          protected abstract void onHandleIntent(@Nullable Intent intent);
      }
      

      IntentService 的源码中,我们主要看三点:

      • mServiceLooper 变量,它是一个 Looper 对象
      • mServiceHandler 变量,它继承了 Handler
      • threadonCreate() 方法中的局部变量,是一个 HandlerThread 变量

      我们开始一步一步分析:在 onCreate() 中,创建了 thread 变量,并且获取到 looper ,传递给 mServiceHandler 对象,保证 serviceHandlerhandleMessage(Message msg) 在新开的线程中执行任务。

      onStart() 中,利用 mServiceHandler 发送一个 msg , 当 IntentService 执行到这的时候,mServiceHandler 就开始调用 handlerMessage(Message msg) ,我们看到在这里面,源码是直接调用了抽象方法 onHandlerIntent() 方法,这个方法会在我们自定义的 IntentService 中进行重写,也就可以进行耗时操作了。

      HandlerThreadIntentService 的源码在知晓 Handler 分发消息原理后很容易就理解,如果你在上面的分析中发现了不足或者认为不正确的地方,欢迎留言指正或者扫描下方的二维码联系我本人沟通交流,谢谢!

      扫描关注

    相关文章

      网友评论

        本文标题:Android源码系列二:HandlerThread和Inten

        本文链接:https://www.haomeiwen.com/subject/ziqctctx.html