Android中更新UI的三种方式:
1.在工作线程中更新UI
2.使用AsyncTask
3.使用Handler
本博客的界面用的同一个xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <TextView
android:id="@+id/hello_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" /> <Button
android:id="@+id/change_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change"
android:textAllCaps="false"/></LinearLayout>
1.在工作线程中更新
在上一篇博客中,我写到工作线程中不能对UI控件进行操作,但最后提到了(Android系统提供了一些工具用于在工作线程中更新主线程)
(1)使用View的postInvalidate()方法刷新页面
(2)使用Activity的runOnUiThread()方法更新UI
(3)使用View的post()和postDelayed()方法更新UI
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); final TextView tv = (TextView) findViewById(R.id.hello_text);
Button bt = (Button) findViewById(R.id.change_btn); final ExecutorService mThreadPool = Executors.newCachedThreadPool();
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mThreadPool.execute(new Runnable() {
@Override
public void run() {
//刷新界面
// tv.postInvalidate(); //使用Activity的runOnUiThread()方法更新UI
// MainActivity.this.runOnUiThread(new Runnable() {
// @Override
// public void run() {
// tv.setText("OH,I am Fine!!!");
// }
// }); //使用View的post()方法更新UI
// tv.post(new Runnable() {
// @Override
// public void run() {
// tv.setText("Hi,Fresh By Post");
// }
// }); //使用View的postDelayed()方法更新UI
tv.postDelayed(new Runnable() {
@Override
public void run() {
tv.setText("Hi,Fresh By postDelayed :");
}
},1000);
}
});
}
});
}
}
2.使用AsyncTask
AsyncTask是Android给我们提供的一种轻量级的异步任务类
我们做一个点击按钮后,demo会进行10s的倒计时
我们重写了doInBackground()后,剩下5个回调方法,他们也是AsyncTask中的生命周期方法,我们在相应的方法中进行初始化,赋值等操作。(下面的代码中有详细的备注)
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Button bt = (Button) findViewById(R.id.change_btn);
final ExecutorService mThreadPool = Executors.newCachedThreadPool();
bt.setOnClickListener(new View.OnClickListener() {
MyAsyncTask myAsyncTask;
@Override
public void onClick(View v) {
myAsyncTask = new MyAsyncTask();
myAsyncTask.execute(Long.valueOf("10"));
}
});
} class MyAsyncTask extends AsyncTask<Object,String,String>{
TextView tv;
@Override
protected void onPreExecute() {
tv = (TextView) findViewById(R.id.hello_text); tv.setText("倒计时开始!");
} /**
* doInBackground()方法是必须重写的一个方法
* 唯一的一个运行在工作线程中的方法
* 用来执行在工作线程中要执行的任务
*/
@SuppressLint("WrongThread")
@Override
protected String doInBackground(Object... objects) {
if (objects.length == 1 && objects[0] instanceof Long){
Long inputTime = (Long) objects[0];
for (;inputTime > 0;inputTime--){
publishProgress(inputTime + "s"); //传给onProgressUpdate()的参数
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}else{
//这里用到了上面的线程中更新UI的方法,不是AsyncTask更新UI的方法
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText("倒计时失败");
}
});
cancel(true);
}
return null;
} /**
* onProgressUpdate()方法是运行在主线程中的方法
* 所以我们在这里可以直接对UI进行更新
*
* 我们下面获取的values是上面publishProgress传的参数
* (本demo中只有一个String类型的参数)
*/
@Override
protected void onProgressUpdate(String... values) {
tv.setText(values[0]);
} /**
* onPostExecute()方法是doInBackground()方法执行完毕后执行的方法
*/
@Override
protected void onPostExecute(String s) {
tv.setText("倒计时完毕");
} /**
* 取消时的回调方法
*/
@Override
protected void onCancelled(String s) {
super.onCancelled(s);
}
}
}
效果截图:
3.使用Handler更新UI
Handler是Android消息机制的上层接口。Handler是专门用来在线程之间传递消息的工具类,主要用于UI界面的更新,消息的传递与处理。
Handler发送消息的两种方法:
1.send系列方法:用于发送一个包含数据的Message对象,并在handleMessage(Message message)方法中处理。(下面demo使用的方法)
2.post系列的方法:用于发送一个Runnable对象,并在MessageQueue收到消息时执行。
public class MainActivity extends AppCompatActivity {
private static final int CHANGE = 1;
private TextView tv; private final MyHandle handle = new MyHandle();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Button bt = (Button) findViewById(R.id.change_btn);
tv = (TextView) findViewById(R.id.hello_text); bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
Message ms = new Message();
ms.what = CHANGE;
handle.sendMessage(ms);
}
}).start();
}
});
} class MyHandle extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case CHANGE:
tv.setText("hello, Changed by Handle!!!");
break;
default:
break;
}
}
}
}