每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),主线程负责处理和ui相关的事件,因此主线程通常又叫UI线程。而由于Android采用UI单线程模型,所以只能在主线程中对UI元素进行操作。
在android app开发的过程中,为了保证我们的应用程序保持响应,一个好的实践就是将执行缓慢的、计算耗时的操作从应用程序的主线程移进一个子线程中,否则,将会发生ANR的错误,或者造成主线程堵塞,主界面刷新异常。所有的Android应用程序——包括Activity、Service和Broadcast Receivers——在应用程序主线程中启动。因此,任何组件中耗时的进程将会阻塞包括Service和不可见的Activity等其他组件。你不仅仅只想避免这种情况的发生,更不想对话框关闭。那就是用后台线程处理这些耗时操作吧,包括文件操作、网络查找、数据库事务和复杂计算。
开发音乐播放器在线歌词下载的过程中,在第一次进入播放界面时,下载歌词,会造成主线程的堵塞,UI刷新异常,使用了Handle+Thread的实现了非主线程更新UI界面,其实很简单,思路如下:
1 在子线程中实现歌词的后台下载,代码如下:
/****************************************************
* the new thread for download the lrc in background
*/
private void DownloadThread(){
new Thread(new Runnable() {
@Override
public void run() {
try{
SearchLyric search = new SearchLyric(mService.getTrackName(),mService.getArtistName());
ArrayList<String> result = search.fetchLyric();
DownloadLrc(result);
} catch (RemoteException ex) {
finish();
} catch (NullPointerException ex) {
// we might not actually have the service yet
ex.printStackTrace();
}
mHandler.sendEmptyMessage(READ_LRC);
}
}).start();
}
2 当下载完成以后,通过 mHandler.senEmptyMessage(READ_LRC)消息给主线程,在主线程中进行相关的UI处理:
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
case READ_LRC:
相关的操作,开始启动读取歌词的线程;
break;
}
}
通过handle+thread很好的解决了主线程中UI堵塞的问题,有些开发者不清楚,会在子线程刷新界面,代码则会报错。