android-----在子线程中更新UI操作的方法

      大家都知道android是不允许在子线程中更新UI操作的,所有更新操作都应该在主线程中完成,因而有了异步消息处理机制,具体源码分析见android-----Handler消息处理机制那么除了通过sendMessage以及handleMessage还有哪些方法可以在子线程中书写更新UI操作的代码呢?

      (1)通过Handler的post方法;

      (2)通过View的post方法;

      (3)通过Activity的runOnUiThread方法;

(1)通过Handler的post方法

 public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
可以看到post方法实际上调用的是sendMessageDelayed方法,这个方法的第一个参数是一个Message对象,通过getPostMessage方法将当前的Runnable对象封装成一个Message对象:

 private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }
也就是会把Mesasge的callback属性设置为Runnable对象,而sendMessageDelayed会调用sendMessageAtTime方法,该方法会调用enqueueMessage方法将当前对象加入到消息队列中去

当我们的消息队列采用死循环进行消息处理的时候,首先会调用dispatchMessage方法,这个方法的源码:

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
首先会查看当前Message的callback属性是否为null,因为刚刚在post的时候已经设置该callback属性,所以不为null,那么会执行handleCallback方法,该方法的源码:

private static void handleCallback(Message message) {
        message.callback.run();
    }
很简单,就是直接执行当前线程而已啦!

我们来一个实例:

该实例通过点击界面上的按钮,为ImageView设置一张显示图来模拟更新界面:

public class MainActivity extends Activity {

	public Button mButton = null;
	public ImageView mImageView = null;
	public Handler mHandler = null;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mButton = (Button)findViewById(R.id.button);
		mImageView = (ImageView)findViewById(R.id.imageView);
		mHandler = new Handler();
		mButton.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				new Thread(){
					public void run() {
						mHandler.post(new Runnable() {
							
							@Override
							public void run() {
								//更新UI的具体操作(我们以加载一张图片到ImageView为例进行)
								mImageView.setBackgroundResource(R.drawable.ic_launcher);
							}
						});
					};
				}.start();
			}
		});
	}
}

(2)通过View的post方法

首先先去View中查看此post方法:

 public boolean post(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.post(action);
        }
        // Assume that post will succeed later
        ViewRootImpl.getRunQueue().post(action);
        return true;
    }
很明显第4行我们发现其实实际上View中的post方法本质上还是调用的Handler的post方法

(3)通过Activity的runOnUiThread方法

再来看看Activity的runOnUiThread方法:

public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }
那么很简单的一点,第2行首先判断当前线程是不是可以更新UI操作的主线程,如果不是的话,第3行同样也是调用的Handler的post方法,如果是主线程的话,则直接执行当前线程就可以啦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值