day 17 面试题:Handler相关

面试题:

Handler相关
1. 谈谈Handler消息机制,有什么作用,有哪些要素,流程是怎样的?
2. 为什么系统不建议在子线程访问UI?
3. 一个Thread可以有几个Looper?几个Handler?
4. 如何将一个Thread线程变成Looper线程?Looper线程有哪些特点?
5. 可以在子线程直接new一个Handler吗?怎么做?
6. Message可以如何创建,哪种效果最好?为什么?
7. 这里的ThreadLocal有什么作用?
8. 主线程中的Looper的轮询死循环为何没有阻塞主线程?
9. 使用Handler的postDealy()后消息队列会发生什么变化?

1. 谈谈Handler消息机制,有什么作用,有哪些要素,流程是怎样的?

此节参考我另一篇文章,写的是Handler的工作流程和关键对象间的关系的。

2. 为什么系统不建议在子线程访问UI?

标准回答

首先UI控件是线程不安全的,如果多线程并发访问UI控件可能出现不可预期的状态

那为什么不对UI控件加上锁呢?

  1. 加锁会让UI访问的逻辑变得更加复杂
  2. 锁机制会降低UI访问的效率,因为锁会阻塞某些线程

鉴于以上几点,安卓的UI访问采用单线程模式来处理。如果在非UI线程访问UI会抛出CalledFromWrongThreadException异常。

3. 一个Thread可以有几个Looper?几个Handler?

由于使用了ThreadLocal机制,所以注定了一个线程只能有一个Looper,但Handler可以new无数个。

4. 如何将一个Thread线程变成Looper线程?Looper线程有哪些特点?

经过如下3个步骤就可以将一个线程变成Looper线程,无参构造创建的Handler是和当前线程的Looper绑定的。

Looper.prepare();
Handler handler = new Handler();
Looper.loop();

looper线程跟普通线程不一样的是可以使用Handler进行传递消息。

5. 可以在子线程直接new一个Handler吗?怎么做?

  1. 如果是子线程的Handler,看上一个步骤中的逻辑

  2. 如果是创建主线程的Handler,则需要传入MainLooper

     Handler mainHandler = new Handler(Looper.getMainLooper());
    

6. Message可以如何创建,哪种效果最好?为什么?

创建Message的三种方式:

Message message = Message.obtain();
Message message = handler.obtainMessage();
Message message = new Message();

前两种都是从消息池中返回一个新的实例,能有效避免重复创建Message。

7. 这里的ThreadLocal有什么作用?

主要用来存储Looper,保证Looper的唯一性。

8. 主线程中的Looper的轮询死循环为何没有阻塞主线程?

主线程其实就是一个默认实现了Looper的无限循环的线程,而各个需要在主线程执行的逻辑都会通过Handler来处理,MessageQueue中没有Message的时候,线程是不会卡住的,因为什么也没有执行。而主线程在处理UI的操作或者Activity的生命周期在执行时,如果超过一定时间就会报ANR。

9. 使用Handler的postDealy()后消息队列会发生什么变化?

postDelay的Message并不是等待一段时间再放入MessageQueue,而是将当前Message的delay时间和队头的Message比较,按照触发时间进行排序,到对应时间再唤醒并执行Message。

你可能感兴趣的:(面试,安卓进阶,算法题面试专栏)