阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Android消息机制Handler用法

34次阅读
没有评论

共计 2862 个字符,预计需要花费 8 分钟才能阅读完成。

导读 这篇文章介绍了 Android 消息机制 Handler 用法总结,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
1. 简述

Handler 消息机制主要包括:MessageQueue、Handler、Looper、Message。

  • Message:需要传递的消息,可以传递数据;
  • MessageQueue:消息队列,但是它的内部实现并不是用的队列,而是通过单链表的数据结构来维护消息列表,因为单链表在插入和删除上比较有优势。主要功能是向消息池投递消息(MessageQueue.enqueueMessage)和取走消息池的消息(MessageQueue.next)。
  • Handler:消息辅助类,主要功能是向消息池发送各种消息事件(Handler.sendMessage)和处理相应消息事件(Handler.handleMessage);
  • Looper:消息控制器,不断循环执行(Looper.loop),从 MessageQueue 中读取消息,按分发机制将消息分发给目标处理者。
2. 异步线程切换原理
class LooperThread extends Thread {
      public Handler mHandler;
  
      public void run() {Looper.prepare();
  
          mHandler = new Handler() {public void handleMessage(Message msg) {// process incoming messages here}
          };
  
          Looper.loop();}
  }

每一个异步线程,都维护着唯一的一个 Looper,每一个 Looper 会初始化(维护)一个 MessageQueue,之后进入一个无限循环一直在读取 MessageQueue 中存储的消息,如果没有消息那就一直阻塞等待。

我们在实例化 handler 的过程中,会先得到当前所在线程的 looper 对象,之后得到与该 looper 对象相对应的消息队列,看源码 Handler 中持有 Looper、MessageQueue。

private static void handleCallback(Message message) {message.callback.run();
}
 
final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;

当我们发送消息的时候,即 handler.sendMessage 或者 handler.post,会将 msg 中的 target 赋值为 handler 自身,这就是实现 message 从一个线程到另外一个线程的传递的本质,之后加入到消息队列中。

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}

我们一般会重写 handlerMessage 方法处理消息,这将会在 msg.target.disPatchMessage 方法中被回调,从而实现了 message 从一个线程到另外一个线程的传递。

3. 总结
  • 1.Handler 的背后有 Looper、MessageQueue 支撑,Looper 负责消息分发,MessageQueue 负责消息管理;
  • 2. 在创建 Handler 之前一定需要先创建 Looper,Looper 有退出的功能,但是主线程的 Looper 不允许退出;
  • 3. 异步线程 Looper,Looper.prepare() 创建 Looper,Looper.loop() 开始轮询,需要自己调用 Looper.myLooper().quit() 退出;
  • 4.Runnable 被封装进了 Message,可以说是一个特殊的 Message;
  • 5.Handler.handleMessage() 所在的线程是 Looper.loop() 方法被调用的线程;
  • 6.Handler 内存泄漏的原因

原因:MessageQueue 持有 Message,Message 持有 activity,delay 多久,message 就会持有 activity 多久。

解决方案:静态内部类、弱引用,最后不要忘记调用 Handler.removeCallbacksAndMessages(null) 清空所有消息。

public class SampleActivity extends Activity {
  
  /**
   * Instances of static inner classes do not hold an implicit
   * reference to their outer class.
   */
  private static class MyHandler extends Handler {private final WeakReference mActivity;
  
    public MyHandler(SampleActivity activity) {mActivity = new WeakReference(activity);
    }
  
    @Override
    public void handleMessage(Message msg) {SampleActivity activity = mActivity.get();
      if (activity != null) {// ...}
    }
  }
  
 // MyHandler
 private final MyHandler mHandler = new MyHandler(this);
  
  /**
   * Instances of anonymous classes do not hold an implicit
   * reference to their outer class when they are "static".
   */
  private static final Runnable sRunnable = new Runnable() {
      @Override
      public void run() { /* ... */}
  };
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
  
    // Post a message and delay its execution for 10 minutes.
    mHandler.postDelayed(sRunnable, 1000 * 60 * 10);
     
    // Go back to the previous Activity.
    finish();}
  
  @Override
  protected void onDestroy() {super.onDestroy();
        //mHandler.removeCallbacksAndMessages(null);
    }
}

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-07-25发表,共计2862字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中