android post 复杂对象,Android UI更新方式之View.post()详解

今天来谈谈利用View类的post() 方法来更新UI。

或许有人会问在Android系统设计的时候为什么不引入多线程直接操作UI呢?

为了回答这个问题,我们首先可以思考引入多线程操作UI会带来哪些问题?

1 线程同步问题

多个线程同时操作一个对象,为保证互斥资源数据的安全性就要进行线程同步,由于线程执行时间片和执行顺序的不确定性,由线程同步引起的编程复杂性会有很大提高。

2 效率的问题

代码中进行线程同步会使得没有持有锁的线程等待,使得并行处理在访问互斥资源时变成串行,拖慢程序执行速度。

基于此种考虑,Android设计了一套机制来保证线程更新UI的安全和高效。大体设计思路是:

1.主线程持有一个消息队列MessageQueue用来存放Message(消息),Message中存放的是需要执行的代码逻辑,例如更新UI,根据Activity状态回调生命周期相应方法等操作。

2.创建一个Lopper对象来不断的(可认为是死循环)从MessageQueue中取出Message(消息)进行处理。

3.提供了Handler类来操作MessageQueue,利用Handler的sendMessage方法来向UI线程发送消息(存放操作)。

队列是FIFO(先进先出)的数据结构,这样UI线程不断的从消息队列中取出Message进行处理,处理完毕取出下一个Message,直到MessageQueue中的Message全部处理完毕,继续不断轮询等待新消息进行处理。

为了方便编码操作UI,Android为View类提供了post()方法来传入一个实现了Runnable接口的对象,注意调用Runnable的并不一定要新建线程,而是标示出要调用该对象run()方法内的代码逻辑。所以在其中不能有耗时操作。查看View中post()方法的源码点我点我

View.post():

public boolean post(Runnable action) {

Handler handler;

AttachInfo attachInfo = mAttachInfo;

if (attachInfo != null) {

handler = attachInfo.mHandler;

} else {

// Assume that post will succeed later

ViewRootImpl.getRunQueue().post(action);

return true;

}

return handler.post(action);

}

Handler.post():

public final boolean post(Runnable r){

return sendMessageDelayed(getPostMessage(r), 0);

}

Handler.sendMessageDelayed()

public final boolean sendMessageDelayed(Message msg, long delayMillis){

if (delayMillis < 0) {

delayMillis = 0;

}

return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);

}

......

可以看到 post()方法中的参数签名叫做 action,也表示要调用的动作的含义。在此方法中最终还是调用Handler来向消息队列中添加Message,通过Looper的不断循环使得代码逻辑最终得到处理。

需要提醒一点,Android的View绘制是在主线程中,所以在绘制View的时候如果有复杂耗时的操作,就会导致用户的触摸事件无法快速传递到MessageQueue中,应用无法及时响应用户的操作而导致用户体验差。遇到此类问题的时候可以使用SurfaceView来代替View的绘制。

好了,本文到此为止,咱们下篇再见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值