[Android实习面试]复习准备1——Handler机制(Kotlin)

Handler机制几乎是面试必考

前向问题

        在需要在子线程中进行UI界面的更新时,如果直接像下述代码一样对textView这个控件进行更新,会导致系统报错。

        原因是Android并不允许在子线程中进行UI操作。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        changeTextBtn.setOnClickListener {
        thread {
            textView.text = "Nice to meet you"
        }
    }
}

解决方法 

        解决方法就是用到了 Handler机制,通过使用Handler,将上述代码修改为以下代码。

class MainActivity : AppCompatActivity() {
    val updateText = 1
    val handler = object : Handler(Looper.getMaininLooper()) {
        override fun handleMessage(msg: Message) {
            // 在这里可以进行UI操作
            when (msg.what) {
                updateText -> textView.text = "Nice to meet you"
            }
        }
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        changeTextBtn.setOnClickListener {
            thread {
                val msg = Message()
                msg.what = updateText
                handler.sendMessage(msg) // 将Message对象发送出去
            }
        }
    }
}

详细解析

        由于在子线程中并不能直接对UI进行操作,于是就在子线程中创建了一个Message对象msg,并将其的what字段的值指定为updateText,然后调用handler的sendMessage(msg)方法将msg发送出去。

        在发送出去后,Handler就会接收到这条Message,然后会调用其自身的handleMessage()方法,并且这个方法是在主线程中运行的(可以更新UI)。

        在这里我们重写了handleMessage()方法,判断当msg.what=updateText(即1)的时候,就执行textView.text = "Nice to meet you"语句,更新界面UI。


拓展说明

        Android中的异步消息处理主要由4个部分组成:Message、Handler、MessageQueue和Looper。

1. Message:

Message主要用于在线程之间传递消息,其可以携带少量的信息,例如what字段,arg1、arg2(都只能携带整形数据)和obj字段(Object对象)。

  • what;
  • arg1和arg2:携带整形数据;
  • obj:携带Object对象

2. Handler:

Handler主要用于发送和处理消息,其部分方法如下:

  • 发送消息:sendMessage()、post();
  • 处理/接收消息:handleMessage()

3. MessageQueue:

MessageQueue是消息队列,主要用于存放所有通过Handler发送的消息。存放在这个队列中等待Handler的处理(即handleMessage()方法)。

4. Looper:

Looper针对的是每个MessageQueue,是每个线程中的MessageQueue的管家,调用Looper的loop()方法后,就会进入一个无限循环当中,然后每当发现MessageQueue中存在一条消息时,就会将它取出,并传递到Handler的handleMessage()方法中。每个线程中只会有一个Looper对象。

        了解了上述的Android的异步消息处理后,就可以详细解释一下上述“解决方法”的整个工作流程了,整个流程大体如下:

  1. 首先是在子线程创建一个Message;
  2. 使用一个Handler将这个Message发送出去;
  3. 发送出去之后,这条Message就会被添加到MessageQueue队列中等待被处理;
  4. Looper则会一直尝试从MessageQueue中取出待处理消息,然后发回Handler的handleMessage()方法中进行处理。

        由于我们在Handler的构造函数中我们传入了Looper.getMainLooper(),所以此时handleMessage()方法中的代码也会在主线程中运行。其整个过程的流程可以用如下图所示的流程图进行解释。(图片来源:《第一行代码》郭霖)


面试真题(某大厂)

  • Handler机制是什么?在没有message的时候为什么不会导致应用程序ANR?

        问题分析:Handler机制可以根据上述介绍答出,而第二个问题则需要进一步的了解。

        原因在于:当没有message的时候,即没有任何消息需要处理,则此时Handler会保持空闲,并不会调用handleMessage()方法执行操作,故此时并不会阻塞主线程。(Handler是异步的)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值