您的位置:首页 > 产品设计 > UI/UE

Android 更新UI方法的深度解析

2016-11-03 14:22 411 查看
      Android开发中,我们总是会遇到更新UI的场景。如果,我们直接在子线程中更新UI,那么会报错!提示我们,要在主线程中更新UI。那么具体更新UI有几种方法呢?下面就来列举这几种更新UI的方法。本篇是结合前面两篇文章有关Handler消息处理,如果你还没有了解,建议先看看这两篇文章,Android
源码解析Handler处理机制(一)和Android 源码解析Handler处理机制(二)

1. Handler。

使用Handler更新UI,不再多说什么了,详情请看上文。

public class SecondActivity extends Activity {
private static final int MSG_WHAT = 101;
TextView tv;
Button btn;
private MyHadler mHandler1;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
tv = (TextView) findViewById(R.id.tv);
btn = (Button) findViewById(R.id.btn);
mHandler1 = new MyHadler();
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
updateUi();
}
});
}

class MyHadler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_WHAT:
String str = (String) msg.obj;
tv.setText(str);
}
}
}

;

/**
*
*/
private void updateUi1() {
new Thread() {
@Override
public void run() {
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message message = mHandler1.obtainMessage();
message.what = MSG_WHAT;
message.obj = "来自子线程的数据";
mHandler1.sendMessage(message);
}
}.start();
}
}


2.Handler的post()方法。

private void updateUi2() {
new Thread() {
@Override
public void run() {
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mHandler1.post(new Runnable() {
@Override
public void run() {
tv.setText(" Handler.post更新UI");
}
});
}
}.start();
}


看看post()方法的源码,

public final boolean post(Runnable r)
{
return  sendMessageDelayed(getPostMessage(r), 0);
}
该方法调用了sendMessageDelayed(getPostMessage(r), 0)发送一条消息,下面首先看看getPostMessage()方法,

private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}

getPostMessage()方法是将Runnable对象转化为消息对象Message的callback属性。而sendMessageDelayed()方法就不多说 了,又回到Handler的处理机制了,详情请看上文Android 源码解析Handler处理机制(二)

PS:在上文中,我们提到过Handler的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,则调用Handler的handleCallback()方法,否则调用Handler对象的handleMessage()方法。更加详细的描述,请看Android 源码解析Handler处理机制(二)

3. Activity的runOnUiThread()方法。

/**
* 通过runOnUiThread更新UI
*/
private void updateUi3(){
new  Thread(){
@Override
public void run() {
try {
Thread.sleep(3*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText("runOnUiThread更新UI");
}
});

}
}.start();
}


看看runOnUiThread()方法的源码,

public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
如果当前线程不是主线程,则调用Handler的post()方法;否则直接执行该方法。最重要的还是Handler的post()方法,相信不需要再多说什么了吧!

4.View.post(Runnable r)方法。

private void updateUi4(){
new Thread(){
@Override
public void run() {
super.run();
tv.post(new Runnable() {
@Override
public void run() {
tv.setText("view post更新UI");
}
});
}
}.start();
}
再来看看post()方法的源码,

public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}

// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue().post(action);
return true;
}

该方法还是调用了Handler的post()方法。Handler的post()方法很重要哦!

(重要的事情说三遍!)有关Handler的post()方法的深度解析,详情请看,你不知道的Runnable接口,深度解析Runnable接口

PS:还可以使用AsyncTask,来请求数据以及更新UI。此处就不多说,详情请看,Android 源码解析AsyncTask(一)和Android
源码解析AsyncTask(二)。

总结:

1.Activity的runOnUiThread()和 View.post(Runnable r)在本质上都是调用Handler的post()方法处理;

2.在子线程中直接更新UI,可以使用 Handler的post(),Activity的runOnUiThread()和 View.post(Runnable r)这三种方法。

推荐文章:Android 源码解析Handler处理机制(一)

                  Android 源码解析Handler处理机制(二)

                 你不知道的Runnable接口,深度解析Runnable接口
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: