使用Android AsyncTask异步线程【转】
转自:http://blog.csdn.net/csheng1204/article/details/7233863
背景:
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 java.net.URL; 5 import java.net.URLConnection; 6 7 import android.app.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 = "http://csdnimg.cn/www/images/csdnindex_logo.gif"; 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(R.id.downloadBtn); 35 logoIv = (ImageView) findViewById(R.id.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://schemas.android.com/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://schemas.android.com/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>
再来个图片刺激下~~效果如下:

最后,放出资源地址,有兴趣可以去下载个回去看看。
浙公网安备 33010602011771号