您的位置:首页 > 移动开发 > Android开发

Android 多线程开发介绍

2017-04-10 16:23 274 查看

Android 多线程

为什么要多线程开发?
    因为默认的我们的任务是在主线程(UI线程)这一单线程模式下执行的,如果主线程执行过于繁重,耗时的操作时,将会阻塞线程, 一旦线程被阻塞,将无法分派任何事件,包括绘图事件。 从用户的角度来看,应用显示为挂起。 更糟糕的是,如果 UI 线程被阻塞超过几秒钟时间(目前大约是 5 秒钟),用户就会看到一个让人厌烦的“应用无响应”(ANR)
对话框。如果引起用户不满,他们可能就会决定退出并卸载此应用。

    因此我们需要新建线程,把耗时的任务放在子线程(非UI线程)中。

一、线程的创建
有两种方式:
1.继承Thread类,实现run()方法

class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}

public void run() {
// 执行耗时操作
. . .
}
}


PrimeThread p = new PrimeThread(143);
p.start();



2.实现Runnable接口,并重写run()方法。并创建实例用做Thread的构造函数。

class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}

public void run() {
//执行耗时操作
. . .
}
}


PrimeRun p = new PrimeRun(143);
new Thread(p).start();


二、线程间通信
耗时任务在子线程执行完成后,要把结果显示出来。

例如,以下代码演示了一个点击侦听器从单独的线程下载图像并将其显示在 ImageView中:
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork("http://example.com/image.png");
mImageView.setImageBitmap(b);
}
}).start();
}

猛一看可能觉得是正常的,但是运行的话,就会出问题,崩溃。原因是,不能在子线程更新UI。
解决方法:1.Activity.runOnUiThread(Runnable)
2.View.post(Runnable)
3.View.postDelayed(Runnable,
long)

例如,你可以通过使用 
View.post(Runnable)
 方法修复上述代码:

public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap bitmap =
loadImageFromNetwork("http://example.com/image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}

4.Handler异步消息处理
Handler mHandler =new Handler(){
    handleMessage(Message message){

        //更新UI
        ...

    }

}

new Thread(new Runnable(){
    //耗时操作

    ...

    mHandler.sendMessage();

});
5.AsyncTask

AsyncTask
 允许对用户界面执行异步操作。 它会先阻塞工作线程中的操作,然后在 UI
线程中发布结果,而无需您亲自处理线程和/或处理程序。

要使用它,必须创建 
AsyncTask
 的子类并实现 
doInBackground()
 回调方法,该方法将在后台线程池中运行。
要更新 UI,应该实现 
onPostExecute()
 以传递 
doInBackground()
 返回的结果并在
UI 线程中运行,以便您安全地更新 UI。 稍后,您可以通过从 UI 线程调用 
execute()
 来运行任务。
例如,您可以通过以下方式使用 
AsyncTask
 来实现上述示例:
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {

protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}

protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}

现在 UI 是安全的,代码也得到简化,因为任务分解成了两部分:一部分应在工作线程内完成,另一部分应在 UI 线程内完成。
下面简要概述了 AsyncTask 的工作方法

可以使用泛型指定参数类型、进度值和任务最终值
方法 
doInBackground()
 会在工作线程上自动执行
onPreExecute()
onPostExecute()
 和 
onProgressUpdate()
 均在
UI 线程中调用
doInBackground()
 返回的值将发送到 
onPostExecute()

您可以随时在 
doInBackground()
 中调用
publishProgress()
,以在
UI 线程中执行 
onProgressUpdate()

您可以随时取消任何线程中的任务
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 多线程