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

Android中更新UI的几种方式

2015-12-30 22:10 453 查看

一、 runOnUiThread

先判断当前线程是否是UI线程,在默认情况下activity有个自己的handler,通过handler会发送一个runnable。

public class five extends AppCompatActivity {
private TextView textView;

private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {

};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_five);
textView = (TextView) findViewById(R.id.textview);
//一般情况下都在子线程中更新UI
new Thread(){

@Override
public void run() {
textView.setText("OK");
try {
Thread.sleep(2000);
//在Runnable中更新UI
handler.post(new Runnable() {
@Override
public void run() {
textView.setText("ok");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}


二、 handler post

通过post发送一个runnable的象,在内部封装成一个message,先调用一个getPostMessage方法。与本质发送message没有什么区别。

public class five extends AppCompatActivity {
private TextView textView;

private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
textView.setText("ok2");
};
};

//直接在一个子线程中给handler发送信息
private void handler2(){
handler.sendEmptyMessage(1);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_five);
textView = (TextView) findViewById(R.id.textview);
//一般情况下都在子线程中更新UI
new Thread(){
@Override
public void run() {
textView.setText("OK");
try {
Thread.sleep(5000);
//在Runnable中更新UI
handler2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}


三、 handler sendMessage

public class five extends AppCompatActivity {
private TextView textView;

private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
};
};
//直接在子线程中更新UI
private void updataUI(){
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText("ok3");
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_five);
textView = (TextView) findViewById(R.id.textview);
//一般情况下都在子线程中更新UI
new Thread(){
@Override
public void run() {
textView.setText("OK");
try {
Thread.sleep(5000);
//在Runnable中更新UI
updataUI();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}


四、 view post

先判断一个AttachInfo,若不为空,通过AttachInfo得到一个handler去发送一个runnable,若为空则通过ViewRootImpl去更新UI。

public class five extends AppCompatActivity {
private TextView textView;

private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
textView.setText("ok2");

4000
};
};

//通过view自己发送Runnable
private void viewUI(){
textView.post(new Runnable() {
@Override
public void run() {
textView.setText("OK4");
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_five);
textView = (TextView) findViewById(R.id.textview);
//一般情况下都在子线程中更新UI
new Thread(){
@Override
public void run() {
textView.setText("OK");
try {
Thread.sleep(5000);
//在Runnable中更新UI
viewUI();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}


总结:本质都是通过handler去更新UI,只是在内部有一些代码上的差异。

五、非UI线程真的不能更新UI么

1)如下程序可以执行

new Thread(){
@Override
public void run(){
textView.setText("OK");
}
}.start();


2)如下程序会报错

new Thread(){
@Override
public void run() {
try {
Thread.sleep(5000);
textView.setText("OK");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();


原因:

所有更新UI的操作都会调用View的invalidate()方法,在我们调用textView.setText()方法后,内部会调用invalidate()方法。其内部,主要用于判断当前线程是否在UI线程更新的操作在ViewParent类中(有一个checkThread()//用于检查当前更新操作是都在主线程中,当前线程是否和UI线程相等)。

然而(1)中因为onResume方法在onCreate方法之前,所以还未能检查。但是不建议以这种方式更新UI。

六、使用handler时所遇到的问题

1、两个异常

1)错误:Only the original thread that created a view hierarchy can touch its views

原因:mThread是在UI线程(activityThread)中创建,若更新UI操作在子线程中,则会抛出异常。

2)错误:Can’t create handler inside thread that has not called Looper.prepare()

原因:在用到handler时必须指定一个looper对象 相关
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android handler