做android开发的都知道,我们在主线程中不能进行耗时太久的操作,否则就可能报ANR,所有耗时的操作都要异步进行。android中的异步方法也很多,可以用Handler,可以用Thread及Runnable等。今天我们用安卓自带的异步工具AsyncTask来实现耗时操作:从网络下载文件。先对AsyncTask作个简单的介绍,下面的介绍也主要是参考网上资料: 

1,AsyncTask定义了三种泛型类型 Params,Progress和Result。


  • Params 启动任务执行的输入参数,如网络请求的URL。
  • Progress 后台进行中任务执行进度百分比。
  • Result 后台执行任务完成最终返回的结果,比如String,Bitmap等。


2,使用AsyncTask 最少要重写以下这两个方法:

  • doInBackground(Params…) 后台执行,耗时的操作都可以放在这里(这里不能直接操作UI)。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度,并用进度条显示出来。
  • onPostExecute(Result)  相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回。

3,有进我还需要重写以下这三个方法(非必需):

  • onProgressUpdate(Progress…)   可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
  • onPreExecute() 当任务执行之前开始调用此方法,可以在这里显示进度对话框。
  • onCancelled()   用户调用取消时,要做的操作可以放到这里面处理。

4,使用AsyncTask类,以下是几条必须遵守的准则:

  • AsyncTask的实例和execute方法必须在UI线程中创建,
  • 不要手动调用onPreExecute(), onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...)这4个方法,
  • 该实现的AsyncTask只能被执行一次,否则多次调用时将会出现异常;                                                             下面是我们实现文件下载的例子:
  • 布局:
• <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical" >


     <Button
         android:id="@+id/file_download_btn"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:gravity="center"
         android:textSize="16sp"
         android:text="下载文件" />


 </LinearLayout>
  • Activity代码:
• public class MainActivity extends Activity implements OnClickListener {
/* SD卡根目录 */
private File rootDie;
/* 输出文件名称 */
private String outFileName = "ldm.rar";
/* 进度条对话框 */
private ProgressDialog pdialog;


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkAndCreateDir();
findViewById(R.id.file_download_btn).setOnClickListener(this);
}


@Override
protected Dialog onCreateDialog(int id) {
/* 实例化进度条对话框 */
pdialog = new ProgressDialog(this);
/* 进度条对话框属性设置 */
pdialog.setMessage("正在下载中...");
/* 进度值最大100 */
pdialog.setMax(100);
/* 水平风格进度条 */
pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
/* 无限循环模式 */
pdialog.setIndeterminate(false);
/* 可取消 */
pdialog.setCancelable(true);
/* 显示对话框 */
pdialog.show();
return pdialog;
}


/* 检查sdcard并创建目录文件 */
private void checkAndCreateDir() {
/* 获取sdcard目录 */
rootDie = Environment.getExternalStorageDirectory();
/* 新文件的目录 */
File newFile = new File(rootDie + "/download/");
if (!newFile.exists()) {
/* 如果文件不存在就创建目录 */
newFile.mkdirs();
}
}


/* 异步任务,后台处理与更新UI */
class MyLoadAsyncTask extends AsyncTask<String, String, String> {
/* 后台线程 */
@Override
protected String doInBackground(String... params) {
/* 所下载文件的URL */
try {
URL url = new URL(params[0]);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
/* URL属性设置 */
conn.setRequestMethod("GET");
/* URL建立连接 */
conn.connect();
/* 下载文件的大小 */
int fileOfLength = conn.getContentLength();
/* 每次下载的大小与总下载的大小 */
int totallength = 0;
int length = 0;
/* 输入流 */
InputStream in = conn.getInputStream();
/* 输出流 */
FileOutputStream out = new FileOutputStream(new File(rootDie + "/mydownload1/", outFileName));
/* 缓存模式,下载文件 */
byte[] buff = new byte[1024 * 1024];
while ((length = in.read(buff)) > 0) {
totallength += length;
String str1 = "" + (int) ((totallength * 100) / fileOfLength);
publishProgress(str1);
out.write(buff, 0, length);
}
/* 关闭输入输出流 */
in.close();
out.flush();
out.close();


} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}


/* 预处理UI线程 */
@Override
protected void onPreExecute() {
showDialog(0);
super.onPreExecute();
}


/* 结束时的UI线程 */
@Override
protected void onPostExecute(String result) {
dismissDialog(0);
super.onPostExecute(result);
}


/* 处理UI线程,会被多次调用,触发事件为publicProgress方法 */
@Override
protected void onProgressUpdate(String... values) {
/* 进度显示 */
pdialog.setProgress(Integer.parseInt(values[0]));
}


}


@Override
public void onClick(View v) {
if (v.getId() == R.id.file_download_btn) {
/* 异步下载 */
new MyLoadAsyncTask().execute("http://192.168.1.105:8080/tool.rar");
}
}

 }
  • 最后别忘记在AndroidManifest.xml中加上权限:
• <!-- sdcard读写权限 -->
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <!-- sdcard创建目录与文件权限 -->
     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
     <!-- 网络访问权限 -->
     <uses-permission android:name="android.permission.INTERNET" />