您的位置:首页 > 理论基础 > 计算机网络

AsyncTask下载网络文件,并显示下载进度

2015-08-10 17:32 716 查看

一些说明

ProgressBar.setProgress():

刷新UI操作必须运行在UI线程中,但是setProgress()方法里面已经做了同步操作,所以可以在非UI线程中调用

webView.loadUrl():

耗时操作不能运行在UI线程中,但是loadUrl()方法进过特殊处理,所以可以在UI线程中调用

异步任务demo

> AsyncTask下载网络文件,并显示下载进度

test_AsyncTask.java

package com.example.testasynctask;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class test_AsyncTask extends Activity {

private ProgressBar pb_down;
private TextView tv_downProgress;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_async_task);
Button btn_down = (Button) findViewById(R.id.btn_down);

btn_down.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String downloadUrl = "http://501xm.cache.cheerpic.com/source/chizi/201508/32283-20150804.apk";
String saveDir = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/test/download";
Log.d("pointwall", saveDir);
DownTask downTask = new DownTask();
downTask.execute(downloadUrl, saveDir);
}
});
}

class DownTask extends AsyncTask<String, // Params,启动任务时传入的参数类型
Integer, // Progress,后台任务执行中返回值的类型
String// Result,后台任务执行完成返回结果的类型
> {

/**
* 执行后台耗时操作前被调用,通常完成一些初始化操作,运行在主线程
*/
@Override
protected void onPreExecute() {
tv_downProgress = (TextView) findViewById(R.id.tv_downProgress);
pb_down = (ProgressBar) findViewById(R.id.pb_down);
pb_down.setMax(100);
}

/**
* 必须重写,异步执行后台将要完成的任务,运行在子线程
*/
@Override
protected String doInBackground(String... params) {
String downloadUrl = params[0];
String saveDir = params[1];

try {
int currentProgress = 0;// 当前已下载文件长度
URL url = new URL(downloadUrl);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(8000);
conn.setReadTimeout(8000);
if (conn.getResponseCode() == 200) {
int length = conn.getContentLength();
InputStream is = conn.getInputStream();

byte[] b = new byte[1024];
int len;

File file2 = new File(saveDir);
if (!file2.exists()) {
file2.mkdirs();
}
File file = new File(saveDir, getFileName(downloadUrl));
RandomAccessFile raf = new RandomAccessFile(file, "rwd");

while ((len = is.read(b)) != -1) {
raf.write(b, 0, len);

currentProgress += len;
// TODO 下载len个长度的字节
int downRate = (int) ((long) currentProgress * 100 / length);
publishProgress(downRate);
}
raf.close();
}
} catch (Exception e) {
e.printStackTrace();
}

return saveDir + getFileName(downloadUrl);
}

/**
* 在doInBackgroung()方法中调用publishProgress()方法 更新任务的执行进度后,就会触发该方法,运行在主线程
*/
@Override
protected void onProgressUpdate(Integer... values) {
int downRate = values[0];
Log.d("ziru", downRate + "");
pb_down.setProgress(downRate);
tv_downProgress.setText("下载了:" + downRate + "%");
}

/**
* 当doInBackground()完成后,系统会自动调用,运行在主线程
*/
@Override
protected void onPostExecute(String result) {
tv_downProgress.setText("下载完成");
}

/**
* 根据下载地址获取app名字
* @param downloadDir 下载地址
* @return app名字,如:32283-20150804.apk
*/
private String getFileName(String downloadDir) {
int index = downloadDir.lastIndexOf("/");
return downloadDir.substring(index + 1);
}

}

}

test_asynctask.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="5dp" >

<ProgressBar
android:id="@+id/pb_down"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp" />

<TextView
android:id="@+id/tv_downProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="等待下载"
android:textSize="20sp" />

<Button
android:id="@+id/btn_down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="下载" />

</LinearLayout>

权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


AsyncTask注意事项

必须在UI线程中创建AsyncTask实例

必须在UI线程中调用AsyncTask.execute()方法

重写的四个方法onPreExecute(), doInBackground(), onProgressUpdate(), onPostExecute()是系统调用的,不应手动调用

每个AsyncTask只能被执行一次,多次调用会引发异常

只有doInBackground()运行在其他线程,onPreExecute(), onProgressUpdate(), onPostExecute()三个方法都运行在UI线程

如何取消AsyncTask

1. 在Activity的onPause()方法中將AsyncTask标记为cancel状态

@Override
protected void onPause(){
super.onPause();
if(mAsyncTask != null &&
mAsyncTask.getStatus() == AsyncTask.Status.RUNNING){
// cancel方法只是將对应的AsyncTask标记为cancel状态,并不是真正的取消线程的执行
mAsyncTask.cancel(true);
}
}


2. 在doInBackground()和onProgressUpdate()方法里做取消异步任务处理

@Override
protected String doInBackground(String... params) {
if(isCancelled()){
break;
}

return null;
}

@Override
protected void onProgressUpdate(Integer... values) {
if(isCancelled()){
break;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: