Handler——小白能懂的原理,老鸟需要的面经

目录

1.机制学习

1.1Handler定义

1.2基本用法

1.3相关类

1.4Handler内部运行机制

1.5消息队列MessageQueue存储方式

2.面试问题经验总结


1.机制学习

1.1Handler定义

发送并处理 与线程的消息队列关联的Message和Runnable

1.2基本用法

1、Message.obtain() 从消息池取得Message

2、Handler().sendMessage(msg) 发送消息

3、Handler().post  将Runnable包装成Message发送

以下提供一个结构代码

import android.os.Handler;  
import android.os.Message;

public class HandlerTestActivity extends AppCompatActivity {

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case 1:
                    // do something
                    break;
            }
        }
    };
    
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_test);
        
        // message形式
        sendMessage();
        // Runnable形式
        postRunnable();
    }
    
    private void sendMessage() {
        Message msg = Message.obtain();  
        msg.what = 1;  
        mHandler.sendMessage(msg);
    }
    
    private void postRunnable() {
        mHandler.post(new Runnable() {  
            @Override  
            public void run() {  
              // do something
            }  
        });
    }
}

1.3相关类

Message是Handler发送的消息实体

MessageQueue是用来将消息按顺序排队的队列

Looper本质就是一个循环,不停的从MessageQueue中取出消息然后处理

1.4Handler内部运行机制

  • 首先,创建一个Message开始的,交给Handler对象发送,sendMessage和sendMessageDelay最终都是在底层调用了sendMessageAtTime()方法将Message对象放入MessageQueue中的
  • 之后,由Looper的loop()循环从MessageQueue中取出Message对象,调用message.getTarget()获取到发送消息的Handler对象,然后再调用handler.dispatchMessage()方法将信息分发给对应handler执行
  • 最后,Handler在dispatchMessage()方法中判断是否有callback 存在,存在则执行callback的onMessageHandler(),最终交由Message.callback执行否则则执行handler的onMessageHandler()方法。

1.5消息队列MessageQueue存储方式

单链表结构,逻辑上属于线性结构,存储(物理)上属于链式结构

                      头尾元素易于添加和删除

                      随机存储,顺序访问

2.面试问题经验总结

  1. Handler的实现原理: Handler内部通过与Looper和MessageQueue的配合,实现了消息处理和线程间通信的功能。

  2. 子线程中能不能直接new一个Handler,为什么主线程可以: 子线程中不能直接new一个Handler,因为子线程默认没有Looper,而Handler的构造函数中需要传入一个Looper对象。主线程可以是因为主线程默认有与之关联的Looper。

  3. 主线程的Looper第一次调用loop方法,什么时候,哪个类: 主线程的Looper第一次调用loop方法是在ActivityThread类的main方法中。

  4. Handler导致的内存泄露原因及其解决方案: Handler持有外部类的引用可能导致内存泄露,解决方案可以使用弱引用或者在不需要Handler时及时removeCallbacksAndMessages(null)。

  5. 一个线程可以有几个Handler,几个Looper,几个MessageQueue对象: 一个线程可以有多个Handler,但通常只有一个Looper和一个MessageQueue对象。

  6. Message对象创建的方式有哪些 & 区别?Message.obtain()怎么维护消息池的: Message对象的创建方式包括new Message()和Message.obtain(),区别在于Message.obtain()会从消息池中获取Message对象,维护消息池是通过一些静态方法来实现的。

  7. Handler有哪些发送消息的方法: Handler的发送消息的方法包括sendMessage(Message msg)、sendMessageDelayed(Message msg, long delayMillis)、sendMessageAtTime(Message msg, long uptimeMillis)等。

  8. Handler的post与sendMessage的区别和应用场景: post方法是sendMessage方法的封装,post方法会自动将Runnable包装成Message对象发送,适用于不需要传递消息数据的情况。

  9. handler postDealy后消息队列有什么变化,假设先 postDelay 10s, 再postDelay 1s, 怎么处理这2条消息: 先postDelay 10s的消息会在消息队列中排在先,后postDelay 1s的消息会在其后。

  10. MessageQueue是什么数据结构: MessageQueue是一个基于链表的数据结构,用于存储消息队列。

  11. Handler怎么做到的一个线程对应一个Looper,如何保证只有一个MessageQueue: Handler内部通过ThreadLocal来实现一个线程对应一个Looper,并保证只有一个MessageQueue。

  12. ThreadLocal在Handler机制中的作用: ThreadLocal在Handler机制中用于存储每个线程对应的Looper对象。

  13. IdleHandler及其使用场景: IdleHandler是一种回调接口,可以在消息队列空闲时执行特定操作,常用于在UI线程空闲时执行一些耗时操作。

  14. 消息屏障、同步屏障机制: 消息屏障是指通过发送特殊的同步消息来控制消息处理的顺序,同步屏障机制用于保证一组消息按照指定的顺序执行。

  15. 子线程能不能更新UI: 子线程不能直接更新UI,必须通过Handler或者其他线程间通信的方式在主线程中更新UI。

  16. 为什么Android系统不建议子线程访问UI: 因为Android中UI操作必须在主线程中进行,子线程直接操作UI可能导致UI线程安全问题。

  17. Android中为什么主线程不会因为Looper.loop()里的死循环卡死: 主线程中Looper.loop()里的死循环会不断从消息队列中取出消息进行处理,不会导致主线程卡死。

  18. Looper.quit/quitSafely的区别: quit方法会立即终止消息循环,quitSafely会等待消息处理完毕后再退出。

  19. 通过Handler如何实现线程的切换: 可以在Handler的构造函数中传入指定的Looper对象来实现线程的切换。

  20. Handler如何与Looper关联: Handler的构造函数中需要传入一个Looper对象来与之关联。

  21. Looper如何与Thread关联: Looper是通过ThreadLocal来与线程关联的。

  22. Looper.loop()源码: Looper.loop()方法是一个无限循环,不断从消息队列中获取消息并分发处理。

  23. MessageQueue的enqueueMessage()方法如何进行线程同步的: enqueueMessage()方法内部使用了锁来实现线程同步。

  24. MessageQueue的next()方法内部原理: next()方法会阻塞等待消息到来,然后返回消息给Looper进行处理。

  25. 子线程中是否可以用MainLooper去创建Handler,Looper和Handler是否一定处于一个线程: 子线程中不能使用MainLooper创建Handler,Looper和Handler通常是处于同一个线程中。

  26. ANR和Handler的联系: 如果在主线程中有耗时操作没有及时处理,会导致ANR,通过Handler可以将耗时操作放到子线程中执行,避免ANR的发生。

  • 10
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值