Android之子线程更新UI
2017-08-09 本文已影响0人
天涯笑笑生
一、简介
- Android 的UI都是由主线程绘制的
- 和其他大多数GUI库一样,Android 的UI也是线程不安全的,要想更新UI元素,一般必须在主线程中进行,否则会出现异常。
- Android的对此一般采用异步消息处理机制。
- AsyncTask使用线程池,所以比handler效率更高
二、异步消息处理机制
//handler
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
// super.handleMessage(msg);
String str = (String) msg.obj;
tv_status.setText(str);
//判断当前函数是否在主线程中执行
boolean result = Looper.getMainLooper() == Looper.myLooper();
Log.d(TAG, "handleMessage: "+result);
}
};
class myThread extends Thread{
@Override
public void run() {
// super.run();
try {
Thread.sleep(1000*6);
String str = "子线程消息";
Message message = new Message();
message.obj = str;
handler.sendMessage(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
-
Message
可以携带少量信息,在线程之间传递,可以使用what、arg1、arg2、obj等字段携带数据。 -
Handler
处理者,用于发送和处理消息。sendMessage()方法发送消息,handleMessage()接收。 -
MessageQueue
消息队列,存放handler发送的消息,每个线程只有一个MessageQueue对象。 -
Looper
MessageQueue的管理者,Looper调用loop()方法,进入无限循环,一发现MessageQueue中有消息,就取出传递给handleMessage(),同样每个线程只有一个Looper对象。
三、AsyncTask
- 使用在代码中做了详细的说明
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TextView tv_text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_text = (TextView) findViewById(R.id.tv_text);
//启动任务
new DownloadTask().execute(10);
}
/**
* 三个泛型参数:
* Params 需要传入后台任务的参数,指定类型
* Progress 后台任务执行时进度,指定进度单位
* Result 执行结果,指定返回类型
*/
class DownloadTask extends AsyncTask<Integer, Integer, Boolean> {
/**
* 后台任务执行前调用,一般用于初始化操作,比如显示一个进度条对话框
*/
@Override
protected void onPreExecute() {
// super.onPreExecute();
tv_text.setText("准备显示");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 方法中的所有代码都在子线程中运行,处理耗时操作,并返回执行结果
*/
@Override
protected Boolean doInBackground(Integer... voids) {
for (int i = 0; i < voids[0]; i++){
try {
Thread.sleep(1000);
//传递进度
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return true;
}
/**
* 使用后台任务传递的参数,在方法中对UI更新
*/
@Override
protected void onProgressUpdate(Integer... values) {
// super.onProgressUpdate(values);
//更新显示
tv_text.setText(""+values[0]);
}
/**
* 后台任务执行完之后调用,并接受返回的参数,更新UI,比如提醒任务结束,关闭对话框等
*/
@Override
protected void onPostExecute(Boolean b) {
// super.onPostExecute(b);
tv_text.setText(""+b);
}
}
}
注:当当前的Activity退出后,开启的任务仍然会继续执行,所以,需要停止时就得重写活动的销毁方法,在方法中停止