Android要求只能在UI线程中更新UI,要想在其他线程中更新UI,大致有四种方式:

1.使用Handler消息传递机制(推荐)

2.使用AsyncTask异步任务(推荐)

3.使用runOnUiThread(action)方法;

4.使用View的post(Runnabel r)方法;

5.使用handler的post

一.Handler:



public class MainActivity extends Activity {

TextView tip;
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
tip.setText("handl更新");
if( msg.what == 0 ){
tip.setText("handl更新");
}
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

tip = (TextView)findViewById(R.id.tip);
}

protected void myClick(View v){
if( v.getId() == R.id.btn ){
new Thread(new Runnable() {
@Override
public void run() {
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
Message msg = handler.obtainMessage();
msg.what = 0;
handler.sendMessage(msg);
}
}).start();
}
}
}


 

二.AsyncTask:

简单示例:



public class MainActivity extends Activity {

TextView tip;
MyAsyncTask myAsyncTask;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

tip = (TextView)findViewById(R.id.tip);

myAsyncTask = new MyAsyncTask();
myAsyncTask.execute();
}

class MyAsyncTask extends AsyncTask<Void,String, Boolean>{

// 非UI线程中,独立线程
@Override
protected Boolean doInBackground(Void... params) {
try{
Thread.sleep(1000*5);
}catch (InterruptedException e){
e.printStackTrace();
}
return true;
}

// UI线程
@Override
protected void onPostExecute(Boolean aBoolean) {
tip.setText("AsyncTask更新了");
}
};
}


 

更详细的用法:​​javascript:void(0)​

三.runOnUiThread

runOnUiThread(Runnable)把更新ui的代码创建在Runnable中,然后在需要更新ui时,把这个Runnable对象传给Activity.runOnUiThread(Runnable)。 这样Runnable对像就能在ui程序中被调用。如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,操作是发布到事件队列的UI线程



public class MainActivity extends Activity {

TextView tip;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

tip = (TextView)findViewById(R.id.tip);

new Thread(new Runnable() {
@Override
public void run() {

try{
Thread.sleep(10*1000);
}catch (InterruptedException e){
e.printStackTrace();
}

runOnUiThread(new Runnable() {
@Override
public void run() {
tip.setText("runOnUiThread");
}
});
}
}).start();
}
}


  

四.使用View的post方法:



public class MainActivity extends Activity {

TextView tv;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

tv = (TextView)findViewById(R.id.tip);

new Thread(new Runnable() {
@Override
public void run() {

try{
Thread.sleep(10000);
}catch (InterruptedException e){
e.printStackTrace();
}

tv.post(new Runnable() {
@Override
public void run() {
tv.setText("view post");
}
});
}
}).start();
}
}


 

五.Handler.post



public class MainActivity extends Activity {

TextView tv;
Handler handler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

tv = (TextView)findViewById(R.id.tip);
handler = new Handler();

new Thread(new Runnable() {
@Override
public void run() {
try{
Thread.sleep(10000);
}catch (InterruptedException e){
e.printStackTrace();
}

handler.post(new Runnable() {
@Override
public void run() {
tv.setText("home");
}
});
}
}).start();
}
}


 

 

可以在子线程里更新的控件及方法:

ProgressBar

ListView 的notifyDataSetChanged()