在android中,经常会碰到网络加载、后台数据处理或者其他一些会非常耗时而且在任务完成后需要根据结果更新UI界面的情况,但是android的UI线程不能够长时间被阻塞,如果超过5秒,会显示应用没有响应。这个时候就非常的悲催了,因此上,这些耗时的操作往往会放入一个子线程去处理,然后根据处理的结果去更新UI界面。但是android的UI线程是非线程安全的,如果在子线程中直接去更新UI控件,通常会跑出一个不能在非UI线程中更新UI线程的异常。这种情况下,通常我们会使用android的Handler类来处理,通过向Handler发送消息在Handler中来做UI的更新,比如,首先把定义一个子线程:
public static final String DATA = "int";
private class TestThread extends Thread{
private int count = 1;
private Bundle bundle = new Bundle();
@Override
public void run() {
try {
while(count<=100){
Message msg = new Message();
bundle.putInt(DATA, count);
msg.setData(bundle);
msg.setTarget(mHandler);
msg.sendToTarget();
count++;
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
子线程定义好以后,再定义一个Handler:
public Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
Bundle data = msg.getData();
int num = data.getInt(DATA);
setTitle(Integer.toString(num));
}
};
最后,在UI线程中启动定义的Thread,比如在OnCreate方法中new TestThread().start();,运行起来会发现应用的title从1增加到100。通过这种方式,我们可以随意的对UI线程进行所需的控制,非常的精确,但是也容易造成代码臃肿。但我们还有另外一种方式来进行异步的调用,那就是AsyncTask,先来看这个类:
AsyncTask<Params, Progress, Result>,该类是一个抽象类,有三个泛型参数,
参数Params,任务启动时的输入参数,比如执行网络下载时的URL路径,或者是参数数组、集合等
参数Progress,任务执行的百分比
参数Result,执行完毕后返回的结果
在使用时,继承该类,重写doInBackground(Object... arg0)方法,该方法中的参数就是在execute(Object... params)方法中传入的参数,注意此方法的运行是在非UI线程中,若在此方法中执行对UI线程的更新,会产生异常,在这个方法执行之前,系统会首先执行onPreExecute()方法,此方法可以对UI线程进行操作,而在doInBackground方法执行完毕以后会将返回的结果传入到onPostExecute(Result result)方法中,这个方法也是在UI线程中,通常的,我们会更具执行结果在这个方法里对UI线程进行更新。下面是一个简单的示例,启动一个实例,首先显示一个进度条,然后在doInBackground中暂停5秒钟,执行以后进度条消失并修改title。
private class Task extends AsyncTask<Object, Long, String>{
private ProgressDialog pd;
@Override
protected void onPreExecute() {
pd = new ProgressDialog(MainActivity.this);
pd.setTitle("进度条");
pd.show();
}
@Override
protected String doInBackground(Object... arg0) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "from doInBackground";
}
@Override
protected void onPostExecute(String result) {
pd.dismiss();
setTitle(result);
}
}
可见,AsyncTask更为直观,但并不能似使用Handler那样随心所欲,具体到要什么时候使用Handler,什么时候使用AsyncTask,需要根据需求来进行详细的分析。
关于一些更深入的研究,请看http://blog.youkuaiyun.com/sunboy_2050/article/details/6713028,或者参见http://developer.android.com/reference/android/os/AsyncTask.html。