马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
目录
1.Handler 的原理
2.Handler核心组件包括
3.Handler的工作流程:
4.一个线程有几个looper,几个消息队列,几个消息
5.延迟消息的实现
6.Handler 为什么会持有 Activity 的引用?
7.Handler 在什么环境下会造成内存泄漏?
8.使用静态内部类创建 Handler,如何实行 Activity 的方法?
9.在主线程和子线程中创建Handler的区别?
10.Looper的创建机会
1.Handler 的原理
Handler 是 Android 中用于线程间通讯的核心机制,尤其用于子线程向主线程发送消息更新 UI。
2.Handler核心组件包括
①Loope: 负责循环从消息队列(MessageQueue)中取出消息,并分发给对应的 Handler 处理。每个线程只能有一个 Looper。
②MessageQueue:一个按实行时间排序的优先级队列,存储待处理的 Message。
③Handler:用于发送消息到 MessageQueue,并处理 Looper 分发的消息。
3.Handler的工作流程:
①Handler 发送消息(如 sendMessage() 或 post(Runnable) ),消息会被插入到关联的 MessageQueue 中。
② Looper 不停循环,从 MessageQueue 中取出符合实行时间的消息。
③消息(的 target字段即发送它的 Handler)会调用 handleMessage() 处理消息。
4.一个线程有几个looper,几个消息队列,几个消息
1 个线程 = 1 个 Looper + 1 个 MessageQueue,可创建多个 Handler。
①每个线程最多一个 Looper,通过 Looper.prepare() 初始化,若重复调用会抛出非常。
②每个 Looper 对应一个 MessageQueue,只能有一个消息队列
③一个线程可以有多个Handler,所有的handler共享同一个Looper和MessageQueue
5.延迟消息的实现
延迟消息是通过 postDelayed() 或 sendMessageDelayed() 发送。
实现原理:
①消息的 `when` 字段被设置为当前时间 + 延迟时间(绝对时间戳)。
②MessageQueue 内部按 `when` 排序,保证最早到期的消息先被处理。
③Looper 取出消息时,会检查当前时间是否到了消息的实行时间,若未到 `when`,则盘算等待时间,进入休眠(通过 `epoll_wait`),制止 CPU 占用。新消息插入时可能唤醒队列。
6.Handler 为什么会持有 Activity 的引用?
①非静态内部类的隐式引用:当 Handler 定义为 Activity 的非静态内部类时,会隐式持有外部类(Activity)的引用。这是 Java 的内部类机制决定的。
②消息队列的引用:Handler 发送的 Message 会持有 Handler 的引用,而消息可能被主线程的 Looper 消息队列(MessageQueue)长时间持有(如延迟消息)。此时,若 Activity 被销毁,但消息未处理完毕,Handler 会制止 Activity 被回收。
7.Handler 在什么环境下会造成内存泄漏?
延迟消息未处理:当 Handler 发送了延迟消息(如 `postDelayed()`)且消息未处理前,Activity 被销毁,但消息仍持有 Handler 的引用,导致 Activity 无法被 GC 回收。
8.使用静态内部类创建 Handler,如何实行 Activity 的方法?
解决方案:弱引用 + 生命周期管理
①静态内部类:将 Handler 定义为静态内部类,制止隐式持有 Activity 的引用。
②弱引用 Activity:通过 `WeakReference` 持有 Activity 的引用,制止强引用导致内存泄漏。
③安全调用:在 `handleMessage()` 中检查 Activity 是否存活,再调用其方法。
- ```java
- public class MyActivity extends Activity {
- private MyHandler mHandler;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mHandler = new MyHandler(this);
- }
- // 静态内部类 + 弱引用
- private static class MyHandler extends Handler {
- private final WeakReference<MyActivity> mActivityRef;
- MyHandler(MyActivity activity) {
- mActivityRef = new WeakReference<>(activity);
- }
- @Override
- public void handleMessage(Message msg) {
- MyActivity activity = mActivityRef.get();
- if (activity == null || activity.isDestroyed()) return; // 检查 Activity 是否有效
- activity.doSomething(); // 调用 Activity 的方法
- }
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- // 移除所有消息,避免无效操作
- mHandler.removeCallbacksAndMessages(null);
- }
- }
- ```
复制代码
9.在主线程和子线程中创建Handler的区别?
选择依据:根据使命是否必要更新UI(主线程)或是否耗时(子线程),决定在哪个线程创建 Handler。
①在主线程中创建 Handler:
主线程创建 Handler:主线程默认已经初始化了 `Looper`,因此可以直接创建 `Handler`绑定到主线程的 Looper,用于更新UI或处理主线程使命。
- ```java
- // 在主线程中创建 Handler
- Handler handler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- // 在主线程中处理消息
- switch (msg.what) {
- case 1:
- // 更新UI
- break;
- }
- }
- };
- // 在子线程中发送消息
- new Thread(() -> {
- Message message = handler.obtainMessage(1);
- handler.sendMessage(message);
- }).start();
- ```
复制代码②在子线程中创建 `Handler:
子线程创建 Handler:子线程默认没有初始化 `Looper`,因此必要手动调用 `Looper.prepare()` Looper.loop()`。绑定到子线程的 Looper,用于实行耗时使命或实现使命队列。
- ```java
- // 在子线程中创建 Handler
- new Thread(() -> {
- Looper.prepare(); // 初始化 Looper
- Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- // 在子线程中处理消息
- switch (msg.what) {
- case 1:
- // 执行耗时任务
- break;
- }
- }
- };
- Looper.loop(); // 启动消息循环
- }).start();
- ```
复制代码
10.Looper的创建机会
①主线程的 Looper 是应用启动时主动创建的(由 `ActivityThread` 的 `main()` 方法主动创建)。
主线程的 Looper 会一直运行,直到应用退出。
- ```java
- public static void main(String[] args) {
- // 初始化主线程的 Looper
- Looper.prepareMainLooper();
- // 创建 ActivityThread 对象
- ActivityThread thread = new ActivityThread();
- thread.attach(false);
- // 启动消息循环
- Looper.loop();
- }
- ```
复制代码②子线程的 Looper必要手动调用 Looper.prepare() 和 Looper.loop() 来创建和启动。
可以通过 `Looper.quit()` 退出消息循环。
- ```java
- new Thread(() -> {
- // 初始化 Looper
- Looper.prepare();
- // 创建 Handler
- Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- // 处理消息
- }
- };
- // 启动消息循环
- Looper.loop();
- }).start();
- ```
复制代码③Activity` 中的 `Looper:
Activity` 默认使用主线程的 Looper`,无需手动初始化。
如果必要在子线程中使用 `Handler`,必须手动创建 `Looper`。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |