当前位置:首页 » 安卓系统 » androidhandler机制

androidhandler机制

发布时间: 2025-01-24 16:41:10

1. 【Android】Message、Handler、MessageQueue、Looper 详解

Handler在Android中主要应用于跨线程通信,确保线程A与线程B之间能够通过共享同一个Handler对象进行消息传递与接收。Handler家族主要包括Message、Handler、MessageQueue与Looper。此框架通过Looper启动消息循环,Handler生成消息,MessageQueue存储消息,Looper处理消息,形成一套高效的消息处理机制。

消息生成与处理的关键在于Message类,其内部维护着一个可用消息对象池(sPool),此池实质上是一个链表结构,sPool指向链表头结点,而next则指向下一个节点。当Handler生成消息时,会将自身作为Message的target,与Message对象绑定。Handler发送消息的途径主要通过enqueueMessage方法,确保每个msg均能绑定一个Handler实例。消息处理则通过Looper循环执行,按照dispatchMessage方法的顺序进行。

Handler家族中的Looper负责创建与管理消息队列,消息队列通过MessageQueue存储待处理的消息。Looper循环执行,从MessageQueue取出消息并进行处理。Looper在主线程中自动创建,而在子线程中则需手动传入Looper对象。

在应用层面,Handler机制可以实现主线程与子线程间的通信。例如,主线程负责处理消息,子线程负责发送消息。这种机制在很多场景下都非常有用,但有时可能需要实现主线程与子线程之间的通信,或者多个子线程之间的通信。这时,可以使用HandlerThread类来实现。

HandlerThread类提供了一种创建子线程并自动启动消息循环的方式,允许主线程向子线程发送消息。实现过程主要包括创建HandlerThread实例、启动线程并创建Looper对象、以及通过Handler对象在子线程中发送消息。这种方式使得多线程间的消息传递更加灵活与高效。

2. Android:在一个非主线程内直接调用UI线程的Handler实例,这样没问题吗

在Android开发中,我们常常遇到线程安全的问题,特别是在子线程和UI线程之间进行交互时。为了保证应用程序的稳定性和用户体验,我们不能直接在子线程中更新UI线程中的UI元素。为了解决这个问题,Android提供了一种机制——Handler。

Handler的工作原理是这样的:当子线程需要更新UI线程中的UI元素时,它会通过发送消息的方式,将需要更新的内容传递给UI线程。这些消息会被放入UI线程的消息队列中,然后由UI线程中的Handler逐个处理。这样,我们就可以在子线程中执行耗时操作,同时在UI线程中更新UI,从而保证了界面的流畅性。

在Android中,创建多线程的方式主要有两种:一种是通过继承Thread类并重写run方法;另一种是通过实现Runnable接口并实现run方法。无论哪种方式,子线程都无法直接修改UI线程中的UI元素,而Handler正是用来解决这一问题的关键。

Handler的主要方法包括post、postAtTime、postDelayed、sendEmptyMessage、sendMessage、sendMessageAtTime、sendMessageDelayed等。这些方法分别用于在主线程中执行Runnable或发送消息。通过这些方法,我们可以灵活地控制消息的发送时机和执行方式。

下面,我们通过一个简单的例子来说明Handler的使用方法。假设我们需要在主线程中的TextView中显示10到100之间的随机数,每隔5秒更新一次,总共更新5次。主要代码如下:

java
int i = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler.post(run);
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg){
String s = String.valueOf(msg.what);
TextView tv = (TextView)findViewById(R.id.textView);
tv.setText(tv.getText() + " " + s);
}
};
Runnable run = new Runnable(){
@Override
public void run(){
Random r = new Random();
int rnum = r.nextInt((100 - 10) + 1) + 10;
handler.sendEmptyMessage(rnum);
handler.postDelayed(run, 5000);
i++;
if (i==5){
handler.removeCallbacks(run);
}
}
};

通过这个例子,我们可以看到Handler在处理子线程与UI线程之间的交互时的重要作用。在实际开发中,我们可以根据具体需求,灵活地使用Handler的各种方法来实现复杂的线程交互逻辑。

3. Android组件系列:再谈Handler机制(Native篇)

前文已介绍过Java层Handler机制的设计与实现,本篇将深入探讨Native层的Looper#loop()为何不会卡死主线程的原理。


从Android 2.3版本开始,Google将Handler的阻塞/唤醒机制从Object#wait() / notify()改为了利用Linux epoll来实现,为的是在Native层引入一套消息管理机制,以支持C/C++开发者。


在Native层实现类似Java层的阻塞/唤醒机制,主要面临两种选择:要么继续使用Object#wait() / notify(),通过Java层通知Native层何时唤醒;要么在Native层重新实现一套阻塞/唤醒方案,并通过JNI调用Java层进入阻塞态。最终,Google选择了后者。


虽然将Java层的阻塞/唤醒机制直接移植到Native层并非必要,使用pthread_cond_wait也能实现相同效果,但epoll提供了一种更高效、更灵活的方案,特别是对于监听多个流事件的需求。


理解I/O多路复用之epoll


epoll是Linux I/O多路复用实现之一,与select和poll并列。它能够高效地同时监听多个流事件,而无需为每个流创建单独的线程或阻塞CPU资源。


epoll通过将流事件转发到用户空间,让用户程序能实时响应事件。为了实现这一功能,epoll与eventfd配合使用。eventfd提供了一个用于累计计数的特殊文件描述符,只有当有新事件发生时,用户程序才能从eventfd中读取到计数增加。


Native Handler机制解析


Native层Handler机制的核心是Looper、MessageQueue和epoll+eventfd的组合。以下是关键步骤:


消息队列初始化

消息队列初始化涉及创建Looper对象,该对象持有mEpollFd和mWakeEventFd两个关键对象。mWakeEventFd用于监听消息队列的新消息,而mEpollFd用于管理监听的流事件。


消息循环与阻塞

Java和Native层的消息队列创建后,线程将阻塞在Looper#loop()方法中。在Java层,消息队列的循环与阻塞由nativePollOnce()方法实现,最终调用到NativeMessageQueue#pollOnce()方法。这个方法将请求转发给Looper#pollOnce()方法执行。


消息发送与唤醒机制

发送消息时,无论是Java还是Native层,最终都会调用到唤醒线程的方法。Java中,通过nativeWake()方法唤醒,而Native层直接通过write()方法向mWakeEventFd写入值来唤醒线程。


唤醒后的消息分发处理

线程唤醒后,首先判断唤醒原因,然后根据不同的情况执行相应的逻辑。关键步骤包括检查mWakeEventFd、处理Native层消息、处理自定义fd的事件等。


结语


通过深入理解epoll机制及其与Native Handler的集成,我们可以清晰地理解Handler机制的底层实现。理解了这些关键技术点后,开发者能够更深入地掌握并优化Android应用中的消息处理逻辑。

4. android之Handler处理机制


在深入研究Handler之前,让我们先思考几个关键问题:


1. Handler的必要性


Android设计Handler机制的主要目的是解决多线程并发中的UI更新问题。设想在一个Activity中,多个线程试图并行更新UI,如果没有恰当处理,会导致界面混乱。而对所有UI操作强制加锁会牺牲性能。


2. Handler的作用


为了解决上述问题,Android提供了一套机制,让所有的UI更新都在主线程的消息队列中异步处理,无需开发者直接关心并发问题。Handler就是实现这一机制的关键。


3. Handler工作原理


Handler与通信的异步同步概念相关。它就像一个异步回调的执行者,子线程通过Handler向主线程发送消息,这些消息在MessageQueue中按顺序等待,Looper负责取出并分发给对应的Handler处理。


4. 如何操作


创建Handler时,它与Looper绑定,通常是当前线程的Looper。在非主线程,需先开启Looper并绑定到Handler,确保消息能正确传递。消息的发送、Looper的轮询和Handler的回调构成了整个工作流程。


5. 关键类理解


包括Message、Handler和Looper,Message用于封装任务数据,Handler负责处理消息,Looper则负责消息队列的管理。创建Handler时,确保在主线程,否则需手动设置Looper。


5. 能讲讲Android的Handler机制吗

Android的Handler机制是通俗讲为了互相发消息,一般是子线程给主线程发消息完成相应操作。

安卓中最常见的操作是子线程操作完事后得到数据想更新UI,安卓有规定不允许在子线程中刷新UI,所以Handler出现了。

使用和理解大致步骤。

  1. 创建全局Handler对象handler,然后在主线程中初始化它(一般在oncreate中),把它的handmessage里面的方法重写,这个方法是收到子线程发给它的消息后执行的逻辑。

  2. 在子线程中获取数据,调用handler.sendmessage,把要发的消息放在message中。message会添加到Messagequue(消息队列中,handler创建就带的)。

3.对象handler被创建和初始化的时候,系统自动会启动Handler.looper,也就是一个消息轮询器,它不断的去查看有没有消息进入到Messagequue(消息队列中),有就取出交给handler的handmessage去处理。//这段逻辑是系统自动执行,理解就行。*纯手打,不骗人~~~

热点内容
androidsdk接入 发布:2025-01-24 20:54:14 浏览:193
我的世界服务器如何使用路由器映射 发布:2025-01-24 20:49:30 浏览:739
脚本操作浏览器 发布:2025-01-24 20:41:40 浏览:296
fast自动获取ip地址服务器无响应 发布:2025-01-24 20:19:13 浏览:710
http加密数据 发布:2025-01-24 20:15:00 浏览:100
中国存储行业排名 发布:2025-01-24 20:02:21 浏览:422
arm编译链 发布:2025-01-24 19:42:12 浏览:700
linuxc的函数返回值 发布:2025-01-24 19:35:23 浏览:665
威纶编程软件反编译 发布:2025-01-24 19:30:26 浏览:49
网络存储单元 发布:2025-01-24 19:28:04 浏览:168