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

Android更新ui 的几种方式?Handler 机制(二)

2015-09-06 18:00 429 查看
activity runonuiThread

首先判断当前线程是不是UI线程,如果不是UI线程,activity自己有一个handler,通过handler的post 方法来发送一个runnable。如果是UI线程就调用UI 线程的run方法,其实内部还是通过handler机制更新UI

handler post(runnable)

内部调用sendMessageDelayed()方法 和sendMessage本质上是相同的

handler sendMessage(最常见)

view post

首先判断AttachInfo是否为空,如果不等于空,则通过AttachInfo拿到handler 。通过AttachInfo.handler.post(runnable)方法来更新UI 。不为空的情况下通过ViewRootImpl.getRunQueue().post(runnable);来更新UI

总结:这四种方法,本质上还是通过handler机制来更新UI 。只是在内部有些代码上的差异

代码如下

public class UpdateUIActivity extends Activity {
private TextView text;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
text.setText("handler2sendEmptyMessage  UI");       };
};

private void handler1() {
// 第一中方式
handler.post(new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
text.setText("handelr  UI");
}
});
}

private void handler2() {
// 第2中方式
handler.sendEmptyMessage(1);
}

private  void updateUI(){
// 第3中方式
runOnUiThread(new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
text.setText("runOnUiThread  UI");

}
});
}

private void viewUI(){
// 第4中方式
text.post(new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
text.setText("viewUIpost  UI");

}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_ui);
text = (TextView) findViewById(R.id.textview1);
new Thread() {

@Override
public void run() {
try {
Thread.sleep(2000);
//handler2();
//updateUI();
//viewUI();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}

}


非UI线程真的不能更新UI么?

在有些情况下非UI 线程是可以更新UI 的。

可以更新的情况

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_ui);
text = (TextView) findViewById(R.id.textview1);
new Thread() {

@Override
public void run() {
text.setText(" UI");

}
}.start();
}


报错的情况

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_ui);
text = (TextView) findViewById(R.id.textview1);
new Thread() {

@Override
public void run() {
try {
Thread.sleep(2000);
text.setText(" UI");
//handler2();
//updateUI();
//viewUI();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}


所有更新UI 的操作都会调用view的 invalidate()方法,当我们调用textview.setText()方法会调用checkForRelayout()方法,重新绘制界面,其内部也会调用invalidate()方法。invalidate()方法内部调用ViewParent的invalidateChild()方法,其实真正判断当前线程是否在UI线程中更新界面的操作就是在ViewParent类当中,ViewParent是ViewRootImpl的一个实现类。对于上面的情况,当线程不休眠的时候ViewRootImpl还没有被创建出来,ViewRootImpl在activity的onResume()方法中被创建,onCreate()方法在onResume()方法之前,所以线程不休眠时就没有创建ViewRootImpl,所以就判断是在UI线程更新UI 就可以更新成功。

Avctivity 的启动类是activityThread
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android ui 线程