安卓handler机制
Handler
Android中 ui的更新需要在主线程中进行,一些耗时的操作我们会放在后台线程中进行,而将执行结果在ui线程中进行。 安卓在设计时就封装了一套消息创建,传递,处理机制,如果不遵循这样的机制,就无法更新ui信息,并抛出异常: 不能在非UI线程中去更新UI。 因此就引入了hanlder机制
特点
a. 允许你去发送并处理一条runnable对象和messageQueue相关联的信息。
b. 每一个handler的实例都与一个单独的线程
c. 当创建一个新的处理程序时,它将绑定到正在创建线程的线程/消息队列, 从那个点开始,它将向该消息队列传递信息和runnables,并在它们从消息队列中释放和执行它们。
运行机制
Handler机制也可以叫做异步机制, 它由四个部分组成分别是: Message. Handler, MessageQueue, Looper
1. Message
Message是在线程中传递的消息,它可以在内部携带少量的消息, 用于在不同线程中交换数据, Message的arg1, arg2可以储存int数据, obj可以携带object数据。
2. Handler
Handler 就是处理者的意思。 它只要用于在子线程发送传送消息对象Message, 在UI对象处理消息对象Message, 在子线程调用sendMessege方法发送消息对象Message, 而发送的消息经过一系列辗转之后,最后会被传递到Handler的HandleMessage方法中,最终在HandleMessage方法中Message对象被处理
3. MessageQueue
顾名思义,它就是消息队列的意思,它用于存放所有通过hanlder发送过来的消息。 这部分消息会一直存放于消息队列之中,等待被处理。 每一个线程只会由一个MessageQueue对象。 其实从字面上就可以看出,MessageQueue底层数据结构是队列,而且这个队列只存放Message对象。
4.Looper
Looper用于管理每个线程中的MessageQueue, 调用Looper的loop()方法后,就会进入一个无限的循环。 每当MessageQueue储存一条信息,Looper就会将这条信息取出, 由Looper按先入先出顺序取出,再根据Message对象的what属性分发给对应的Handler的HandleMessage()方法中。 每个线程只有一个Looper.
Handler怎么用
Handler可以分发Message和 Runnable对象进入主线程中, 每个Handler实例都会绑定到创建它的线程中 它由两个作用:
1.合理调度安排消息和Runnable对象,使他们在将来的某个点执行。
2. 安排一个动作在不同线程执行。
Handler中一些常见的方法:
post(Runnable)直接开启Runnable线程
postAtTime(Runnable,long)在指定的时间long,开始启动线程
postDelayed(Runnable long)在延迟long时间后,启动Runnable线程
sendEmptyMessage(int) 发送指定的消息,通过参数int来区分不同的消息
sendMessage(Message)发送消息到UI线程中
sendMessageAtTime(Message,long) 这个long代表的是系统时间,不推荐用
sendMessageDelayed(Message,long) 此方法long代表调用后几秒后执行。
sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.
handler基本使用:
1)在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法,在 handleMessage 中提供收到消息后相应的处理方法即可。(接收消息,并且更新UI)
- 在新启动的线程发送消息。
public class HandlerActivity extends AppCompatActivity {
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tv.setText("msg.arg1:"+msg.arg1+"--msg.arg2:"+msg.arg2);
}
};
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
initView();
new Thread(new Runnable() {
@Override
public void run() {
Message msg = Message.obatin();//实例化消息对象
msg.arg1 = 99;//携带参数
msg.arg2 = 100;//携带参数
Object str = new Object();//实例化对象
msg.obj = str; //携带参数为实体类对象
handler.sendMessage(msg);
}
});
}
private void initView() {
tv = (TextView) findViewById(R.id.tv);
}
}
总结:
首先在UI线程我们创建了一个Handler实例对象,无论是匿名内部类还是自定义类生成的Handler实例对象,我们都需要对handleMessage方法进行重写,在此方法中我们可以通过参数来接受msg来写接受消息后如何处理。 接着我们创建一个子线程,在子线程中需要更新ui时,新建一个Message对象,并且将消息的数据记录在这个消息对象Message的内部,比如arg1,arg2,obj等, 在通过前面创建的handler的sendMessage方法把次消息给发送出去, 此时这个Message会放入MessageQueue中等待被处理, 此时MessageQueue的管家Looper会不停的把messageQueue存在的消息取出来,通过回调dispatchMessage方法将消息传递给Handler的handleMessage方法,最终前面提到的消息会被Looper从MessageQueue中取出来传递给handleMessage方法,最终得到处理。
本文地址:https://blog.csdn.net/weixin_47285644/article/details/110238446