背景:
1、Android是单线程UI模型,所以假如不另外开辟线程做一些下载图片、获取网络内容的的操作,会使UI给用户一种“很卡”的感觉;
2、假如不引入多线程,很容易导致Application Not Responding 也就是ANR,应用程序无响应,在手机上面一般表现为弹出一个警告窗口,“强制关闭”、“Force Close”这种恶心的问题;
3、Android本身提供一个封装好的异步线程类叫AsyncTask,为我们管理线程起到很好的作用。
AsyncTask<Params, Progress, Result>
用法:
必须继承AsyncTask并重写至少一个方法 doInBackground(Params...),经常使用的是也重写第二个方法 onPostExecute(Result)
参数:
- Params, 开始任务前传入参数,注意的是,可变长输入,可以一次性启动执行多个下载任务,例如传入一组String[];
- Progress,在后台任务计算时,向外发布进程的单位,一般是Int或者Double或者其他;
- Result,后台任务计算结束后,返回的结果
注意以上三个参数皆可为空,只需要传入AsyncTask<Void,Void,Void>即可。
进程4部曲:(其实还有1个~)
- onPreExecute(),在UI线程调用,然后立刻被执行。这个过程一般用来做一些初始化操作,例如显示出一个ProgressBar提示用户任务已经在执行中、例如让启动任务的Button变为Disabled,防止多次执行;
- doInBackground(Params...),当onPreExecute()执行完毕,会立刻在后台线程调用。这个过程一般用来做一些比较耗时的操作,如计算PI(当然没人这么无聊吧~)、例如下载网络图片,结果将会传给最后一个过程onPostExecute(Result)。当然为了使你的程序更加友好,可以显示进度,而具体进度如何,就是通过在这个过程调用 publishProgress(Progress...) 来向外(指UI线程)发布进程。
- onProgressUpdate(Progress...),当 publishProgress(Progress...)被调用时,会在UI线程调用此方法。一般是用来提示用户进度,例如用在Notification上面显示下载进度条;
- onPostExecute(Result),当任务结束时在UI线程调用,传入参数为doInBackground()的结果~~
- onCancelled(),在AsyncTask的cancel()方法被调用时触发调用。
以下是一个自己写的Demo,有一个按钮,按钮启动异步任务下载CSDN logo并显示出来
<注意:以下属性match_parent须在Android2.2之后才可以支持,效果同Android2.1及之前的fill_parent>
AsyncTaskDemoActivity.java
1 package com.csheng.asynctask;
2
3 import java.io.InputStream;
4 import .URL;
5 import .URLConnection;
6
7 import .Activity;
8 import android.graphics.Bitmap;
9 import android.graphics.BitmapFactory;
10 import android.os.AsyncTask;
11 import android.os.Bundle;
12 import android.view.View;
13 import android.view.View.OnClickListener;
14 import android.widget.Button;
15 import android.widget.ImageView;
16
17 public class AsyncTaskDemoActivity extends Activity {
18
19 public static final String TAG = "AsyncTaskDemoActivity";
20
21 private Button downloadBtn = null;
22 private ImageView logoIv = null;
23 /* CSDN logo */
24 private final String LOGO_URL = "";
25
26 @Override
27 public void onCreate(Bundle savedInstanceState) {
28 super.onCreate(savedInstanceState);
29 setContentView(R.layout.main);
30 findViews();
31 }
32
33 private void findViews() {
34 downloadBtn = (Button) findViewById(.downloadBtn);
35 logoIv = (ImageView) findViewById(.logoIv);
36 downloadBtn.setOnClickListener(new OnClickListener() {
37
38 @Override
39 public void onClick(View v) {
40 new DownloadAsyncTask().execute(LOGO_URL);// 启动匿名任务
41 }
42 });
43 }
44
45 private class DownloadAsyncTask extends AsyncTask<String, Void, Bitmap> {
46
47 @Override
48 protected Bitmap doInBackground(String... params) {
49 final String urlStr = params[0];// 取出execute所传入参数
50 URL url = null;
51 try {
52 url = new URL(urlStr);
53 final URLConnection connection = url.openConnection();
54 final InputStream inputStream = connection.getInputStream();
55 final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
56 if (bitmap != null) {
57 return bitmap;// 交给onPostExecute()处理
58 }
59 } catch (Exception e) {
60 e.printStackTrace();
61 }
62 return null;
63 }
64
65 @Override
66 protected void onPostExecute(Bitmap result) {
67 if (result != null) {
68 logoIv.setImageBitmap(result);// 取出doInBackground()的计算结果
69 }
70 downloadBtn.setEnabled(true);
71 super.onPostExecute(result);
72 }
73
74 @Override
75 protected void onPreExecute() {
76
77 downloadBtn.setEnabled(false);// 在整个异步下载期间,不允许重新启动下载任务
78 super.onPreExecute();
79 }
80
81 }
82 }
main.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <RelativeLayout xmlns:android="http:///apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent" >
5
6 <Button
7 android:id="@+id/downloadBtn"
8 android:layout_width="wrap_content"
9 android:layout_height="wrap_content"
10 android:layout_centerHorizontal="true"
11 android:text="@string/downloadText" />
12
13 <!-- 图片放置于按钮下方 -->
14
15 <ImageView
16 android:id="@+id/logoIv"
17 android:layout_width="wrap_content"
18 android:layout_height="wrap_content"
19 android:layout_below="@+id/downloadBtn"
20 android:layout_centerHorizontal="true"
21 android:contentDescription="@string/contentDescription" />
22
23 </RelativeLayout>
strings.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3
4 <string name="app_name">AsyncTaskDemo</string>
5 <string name="downloadText">下载图片</string>
6 <string name="contentDescription">这是一张图片</string>
7 <string name="startDownloadToast">开始下载图片</string>
8 <string name="setImageToast">设置图片资源</string>
9
10 </resources>
AndroidManifest.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <manifest xmlns:android="http:///apk/res/android"
3 package="com.csheng.asynctask"
4 android:versionCode="1"
5 android:versionName="1.0" >
6
7 <uses-sdk android:minSdkVersion="8" />
8
9 <uses-permission android:name="android.permission.INTERNET" />
10
11 <application
12 android:icon="@drawable/ic_launcher"
13 android:label="@string/app_name" >
14 <activity
15 android:name=".AsyncTaskDemoActivity"
16 android:label="@string/app_name" >
17 <intent-filter>
18 <action android:name="android.intent.action.MAIN" />
19
20 <category android:name="android.intent.category.LAUNCHER" />
21 </intent-filter>
22 </activity>
23 </application>
24
25 </manifest>
















