转载请注明本文出自天水笑微的博客(http://blog.csdn.net/fuhaijing2013/article/details/62226825),谢谢支持!
Android的线程主要分两种:主线程和子线程。主线程主要负责处理UI相关的操作,子线程主要负责一些耗时操作,各司其职,如果主线程中处理一些耗时操作(一般大于5s)就会导致程序无法响应异常,同时如果子线程越权处理更新UI操作,亦会出现异常,这也就是大家平常说的Android是线程不安全的。(虽然多有不便,想想也有道理,如果多个线程同时操作UI,那不乱套才怪。)
Android系统提供的线程实现方式主要有:原生的Thread、轻量级AsyncTask、服务IntentService、HandlerThread。
一、Thread+Handler或runOnUiThread实现方式
Thread+handler实现方式基本思路是,开启一个子线程Thread,实现Runnable接口,在run()函数中执行一些耗时操作,然后通过Message与Handler通信,通过Handler切换到主线程中实现UI更新操作(如果不需要更新UI就不需要Handler了,不过这种情况比较少)。代码如下:
protected void DataParerThread() {
Runnable target = new Runnable() {
public void run() {
//耗时操作
//...
Message msg = Message.obtain();
msg.what = 0;
msg.obj = message;
handler.sendMessage(msg);
}
};
new Thread(target).start();
}
}
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
//UI 操作
super.handleMessage(msg);
}
};
Thread+runOnUiThread方式更紧凑一些,直接在Run()函数里通过runOnUiThread函数切换到主线程,实现UI操作。
protected void DataParerThread() {
Runnable target = new Runnable() {
public void run() {
//耗时操作
//...
runOnUiThread(new Runnable() {
public void run() {
//更新UI操作
}
}
}
};
new Thread(target).start();
}
二、AsyncTask封装
AsyncTask是一种轻量级的异步任务类,封装了Thread+handler,底层用到了线程池,是Android为了简化子线程中访问UI的过程而推出的异步实现方式,比Thread+handler更加轻量级,适合并不是特别耗时的后出台任务。
主要有四个核心方法:doInBackground(Params…),onPostExecute(Result),onPreExecute() 、onProgressUpdate(Progress…) ,至少覆盖前两个方法
doInBackground(Params…) 后台执行,比较耗时的操作,这里不能直接操作UI。执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。
onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。
onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
private myAsyncTask extends AsyncTask{
@Override
protected void onPreExecute(){
Log.v("TestActivity","开始执行异步线程");
}
/**
* 这里的Integer参数对应AsyncTask中的第一个参数
* 这里的String返回值对应AsyncTask的第三个参数
* 该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改
*/
@Override
protected String doInBackground(Integer...params){
// 加载网络数据,耗时操作
}
@Override
protected void onPostExecute(Stringresult){
Log.v("TestActivity","结束执行异步线程");
// 更新UI
}
}
三、特殊服务IntentService
IntentService是一种特殊的Service,内部封装了HandlerThread和Handler,与service的不同是当任务结束后可以自己杀死自己节约内存。
可用于执行后台耗时任务,与前两种相比优点是优先级比较高,所以这种方式比较适合执行一些优先级比较高的耗时任务,不容易被杀死。
四、HandlerThread
HandlerThread集成了Thread,是一种可以使用Handler的Thread,很少单独用吧。
五、异同
1) 实现方式方面,AsyncTask方式做了比较好的封装,逻辑更清晰,原生的Thread+Runnable+Handler方式代码不够紧凑(其实还好啦)
2) 性能方面,有一种说法是AsyncTask比起Thread方式耗内存,感觉没啥差别吧,毕竟AsyncTask也是通过封装原生Thread实现的,具体也没验证。
3)灵活性方面,AsyncTask对UI的控制更灵活一些,可以通过提供的接口函数实时更新UI
4)功能方面,AsyncTask的一个缺点是不能灵活的控制线程池,加入一个页面有50个AsyncTask线程访问,切换到另一个界面,新的线程访问可能排到50名开外了,取消操作和优先级设定不好控制。如果遇到这种情况,推荐一些自己封装的ThreadPoolExecutor方式。
六、使用总结
Android为了更方便的在线程中操作Ui,延伸出了AsyncTask,因此如果需要用到与界面相关的线程且不太复杂的时候首选AsyncTask,如果线程主要用来处理数据,不参与界面操作的时候尽量用Thread线程。另外如果在应用中需要启动多个线程的时候,也要使用Thread,它自带多线程处理。AsyncTask适合一些少数数据量的操作。
其实,我平时更倾向于用Tread+runOnUiThread()方式实现,没那么臃肿,还好处多多。