由于Android规定只有UI线程才能更新用户界面和接受用户的按钮及触摸事件,那么就必须保证UI线程不可以被阻塞,从而耗时操作必须要开启一个新的线程来处理!等耗时操作结束以后,必须把最新的数据传给UI线程能处理的地方。
主要有以下四种方法来处理:
1、Handler
Handler用于异步消息处理,在后台线程与UI线程的交互中最常用,Handler自己并不会创建线程,一般Handler用于计划任务和线程间的通信。
Handler处理多线程的原理:
系统启动程序时,会自动为UI线程创建一个消息队列和用于管理这个消息队列的Looper。在创建后台线程时,默认是不会创建Looper和消息队列的。但是可以通过调用Looper.prepare()给后台线程创建Looper和消息队列。
Activity所在的UI线程在创建的时候,就关联了Looper和消息队列(MessageQueue),那么我们又在UI线程里创建了自己的Handler,那么Handler属于UI线程,从而它是可以和UI线程交互的。
UI线程提供消息队列MessageQueue,Handler向其中填写Message,UI线程的Looper一直在进行Loop操作,在MessageQueue中读取符合要求的Message给属于它的Target即Handler来处理,最终被从属于UI线程的Handler的handlMessage(Message msg)方法被调用。
例如:
new TestThread(MainActivity.this).start();
//后台线程类
class TestThread extends Thread
{
Activity activity;
public TestThread(Activity activity) {
this.activity = activity;
}
@Override
public void run() {
//下面代码用来演示Handler方法的实现
Message msg=new Message();
Bundle bundle=new Bundle();
bundle.putString("tag", "Test Handler");
msg.setData(bundle);
new TestHandler(Looper.getMainLooper()).sendMessage(msg);
super.run();
}
}
//用于线程间通信的Handler
class TestHandler extends Handler
{
public TestHandler(Looper looper) {
super(looper);
// TODO Auto-generated constructor stub
}
//在handleMessage里面修改主UI
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
System.out.println("123");
txView.setText((String)msg.getData().get("tag"));
super.handleMessage(msg);
}
}
2、Activity.runOnUIThread(Runnable)
new TestThread(MainActivity.this).start();
//后台线程类
class TestThread extends Thread
{
Activity activity;
public TestThread(Activity activity) {
this.activity = activity;
}
@Override
public void run() {
//下面代码用来演示Activity.runOnUIThread(Runnable)方法的实现
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
txView.setText("Test runOnUIThread");
}
});
}
}
3、View.post(Runnable),View.postDelay(Runnable,long)
new TestThread(MainActivity.this).start();
//后台线程类
class TestThread extends Thread
{
Activity activity;
public TestThread(Activity activity) {
this.activity = activity;
}
@Override
public void run() {
//下面代码用来演示View.post(Runnable)方法的实现
txView.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
txView.setText("Test View.post(Runnable)");
}
});
//下面代码用来演示View.postDelay(Runnable,long)方法的实现
txView.postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
txView.setText("Test View.postDelay(Runnable,long)");
}
}, 1000);
}
}
4、AsyncTask<Params,Progress,Result>
Params,Progress,Result都是数据类型,
Params要处理的数据的类型
Progress处理进度的类型
Result处理后返回的结果
它是一个异步处理的简单方法!
方法的执行顺序:
1)
onPreExecute() --在UI线程中执行,作一些初始化操作
2)
doInBackground(Params... params) --在子线程中执行,进行耗时的后台处理,在该方法中可以调用publishProgress(Progress progress) 进行进度处理
3)
onProgressUpdate(Progress progress) --在UI线程中执行,进行进度实时处理
4)onPostExecute(Result result) --在UI线程中执行, 在doInBackground(Params ... params)返回后调用
5)
onCancelled() --在UI线程中执行,在AsyncTask实例调用cancle(true)方法后执行,作一些清理操作
几点注意:
AsyncTask必须在UI线程中创建,
asyncTask.execute(Params... params) ;在UI线程中执行,且只能执行一次
要想再次调用execute(Params... params),必须重新创建AsyncTask对象
源码示例:
//创建一个用于展示AsyncTask实现交互的TestAsyncTask
new TestAsyncTask().execute("Test"," AsyncTask");
class TestAsyncTask extends AsyncTask<String, Integer, String>
{
//TestAsyncTask被后台线程执行后,被UI线程被调用,一般用于初始化界面控件,如进度条
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
//在PreExcute执行后被启动AysncTask的后台线程调用,将结果返回给UI线程
@Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
StringBuffer sb=new StringBuffer();
for (String string : params) {
sb.append(string);
}
return sb.toString();
}
}
//doInBackground执行完后由UI线程调用,用于更新界面操作
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
txView.setText(result);
super.onPostExecute(result);
}