2017-03-27
原CSDN博客已弃用,文章会逐渐迁移过来。
一、简单理解Demo
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* 运行TestAsyncTask
*/
new TestAsyncTask().execute();
}
private class TestAsyncTask extends AsyncTask{
//一般用于初始化,首先运行
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
//一般处理耗时操作,第二运行,不要在这里面运行与ui控件有关的操作
@Override
protected Object doInBackground(Object... params) {
return null;
}
/*
* 一般用于处理UI界面变化,最后运行
* result是上面doInBackground返回值
*/
@Override
protected void onPostExecute(Object result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
}
二、实践熟悉Demo
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello , Welcome to Andy's Blog!"/>
<Button
android:id="@+id/download"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Download"/>
<TextView
android:id="@+id/tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="当前进度显示"/>
<ProgressBar
android:id="@+id/pb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"/>
</LinearLayout>
MainActivity.java
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity {
Button download;
ProgressBar pb;
TextView tv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pb=(ProgressBar)findViewById(R.id.pb);
tv=(TextView)findViewById(R.id.tv);
download = (Button)findViewById(R.id.download);
download.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DownloadTask dTask = new DownloadTask();
dTask.execute(100);
}
});
}
class DownloadTask extends AsyncTask<Integer, Integer, String>{
//后面尖括号内分别是参数(例子里是线程休息时间),进度(publishProgress用到),返回值 类型
@Override
protected void onPreExecute() {
//第一个执行方法
super.onPreExecute();
}
@Override
protected String doInBackground(Integer... params) {
//第二个执行方法,onPreExecute()执行完后执行
for(int i=0;i<=100;i++){
pb.setProgress(i);
publishProgress(i);
try {
Thread.sleep(params[0]);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "执行完毕";
}
@Override
protected void onProgressUpdate(Integer... progress) {
//这个函数在doInBackground调用publishProgress时触发,虽然调用时只有一个参数
//但是这里取到的是一个数组,所以要用progesss[0]来取值
//第n个参数就用progress[n]来取值
tv.setText(progress[0]+"%");
super.onProgressUpdate(progress);
}
@Override
protected void onPostExecute(String result) {
//doInBackground返回时触发,换句话说,就是doInBackground执行完后触发
//这里的result就是上面doInBackground执行后的返回值,所以这里是"执行完毕"
setTitle(result);
super.onPostExecute(result);
}
}
}
三、简单学习Demo
activity.xml使用系统默认即可,
Java学习代码如下
MainActivity.java
package com.administrator.asynctaskdemo;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";//键盘在空白处输入logt,AndroidStudio会快速生成这行代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// new DownloadAsyncTask().execute("XueXi","KanShu");
new DownloadAsyncTask().execute("XueXi");
}
public class DownloadAsyncTask extends AsyncTask<String,Integer,Boolean>{
/**
* 在异步任务之前,在主线程中
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
//可操作UI
}
/**
* 在另外一个线程中处理事件
* @param params 入参
* @return 结果
*/
@Override
protected Boolean doInBackground(String... params) {//String... strings表示长度是可变参数,
// 比如外部调用时,doInBackground("a");doInBackground("a","b");
// doInBackground("a","b","c");等,参数的数量是可变的
for (int i = 0;i<10000;i++){
Log.i(TAG,"doInBackground:"+params[0]);
//抛出进度
publishProgress(i);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
//也是在主线程中,执行结果处理
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//收到上面抛出的进度,然后处理:也是在UI线程中
}
// @Override
// protected void onCancelled() {
// super.onCancelled();
// }
//
// @Override
// protected void onCancelled(Boolean aBoolean) {
// super.onCancelled(aBoolean);
// }
}
}
四、AsyncTask实现异步下载
步骤
1.网络上请求数据:申请网络权限 读写存储权限
2.布局我们的layout
3.下载之前我们要做什么? UI
4.下载中我们要做什么? 数据
5.下载后我们要做什么? UI
在MainManifest.xml中申请网络权限和读写权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical"
tools:context="com.administrator.asynctaskdemo.MainActivity">
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="15dp"
android:id="@+id/progressBar"/>
<Button
android:text="点击下载"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/button"/>
<TextView
android:text="Hello world! imooc."
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView"/>
</LinearLayout>
MainActivity.java
package com.administrator.asynctaskdemo;
import android.os.AsyncTask;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.w3c.dom.Text;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
/**
* 1.网络上请求数据:申请网络权限 读写存储权限
* 2.布局我们的layout
* 3.下载之前我们要做什么? UI
* 4.下载中我们要做什么? 数据
* 5.下载后我们要做什么? UI
*/
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";//键盘在空白处输入logt,AndroidStudio会快速生成这行代码
public static final String APK_URL = "http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk";
private ProgressBar mProgressBar;
private Button mDownloadButton;
private TextView mResultTextView;
private int INIT_PROGRESSBAR;
private String FILE_NAME = "XueXi.apk";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化视图
initView();
//设置点击监听
setListener();
//初始化UI数据
setData();
}
private void setListener() {
mDownloadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//TODO 18/5/10 下载任务
DownloadAsyncTask asyncTask = new DownloadAsyncTask();
asyncTask.execute(APK_URL);
}
});
}
private void setData() {
mProgressBar.setProgress(INIT_PROGRESSBAR);
mDownloadButton.setText("点击下载");
mResultTextView.setText("准备下载");
}
/**
* 初始化视图
*/
private void initView() {
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mDownloadButton = (Button) findViewById(R.id.button);
mResultTextView = (TextView) findViewById(R.id.textView);
}
/**
* String 入参
* Integer 进度
* Boolean 返回值
*/
public class DownloadAsyncTask extends AsyncTask<String, Integer, Boolean> {
String mFilePath;
/**
* 在异步任务之前,在主线程中
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
//可操作UI 类似淘米,之前的准备工作
mDownloadButton.setText("下载中");
mResultTextView.setText("下载中");
mProgressBar.setProgress(INIT_PROGRESSBAR);
}
/**
* 在另外一个线程中处理事件
*
* @param params 入参 煮米
* @return 结果
*/
@Override
protected Boolean doInBackground(String... params) {//String... strings表示长度是可变参数,
if(params != null&¶ms.length>0){
String apkUrl = params[0];
try {
//构造URL
URL url = new URL(apkUrl);
//构造连接,并打开
URLConnection urlConnection = url.openConnection();
InputStream inputStream =urlConnection.getInputStream();
//获取下载内容的总长度
int contentlength = urlConnection.getContentLength();
//下载地址准备
mFilePath = Environment.getExternalStorageDirectory() // File.separator是字符串/
+ File.separator + FILE_NAME;
//对下载地址进行处理
File apkFile = new File(mFilePath);
if(apkFile.exists()){
boolean result = apkFile.delete();
if(!result){ //如果失败了
return false;
}
}
//已下载的大小 已下载大小/总长度*100等于下载进度
int downloadSize = 0;
//byte数组
byte[] bytes = new byte[1024];
int length;
//创建一个输入管道
OutputStream outputStream = new FileOutputStream(mFilePath);
length = inputStream.read(bytes);
//不断的一车一车挖土,直到挖不倒为止
while ((length = inputStream.read(bytes))!= -1){
//挖到的放到我们的文件管道里
outputStream.write(bytes,0,length);
//累加我们的大小
downloadSize += length;
//发送进度
publishProgress(downloadSize*100/contentlength);
}
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}else{
return false;
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
//也是在主线程中,执行结果处理
mDownloadButton.setText(result?"下载完成"+ mFilePath:"下载失败");
mResultTextView.setText(result?"下载完成"+ mFilePath:"下载失败");
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//收到进度,然后处理:也是在UI线程中
if(values!=null&&values.length>0){}
mProgressBar.setProgress(values[0]);
}
}
}
五、封装成工具类
xml布局如上不变
创建下载工具类
DownloadHelper.java
package com.administrator.asynctaskdemo;
import android.os.AsyncTask;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
/**
* 1.download方法 url localPath listener
* 2.listener :start success fail progress
* 3.用asynctask封装
* Created by Administrator on 2018/5/10.
*/
public class DownloadHelper {
public static void download(String url,String localPath,OnDownloadListener listener) {
DownloadAsyncTask task = new DownloadAsyncTask(url,localPath,listener);
task.execute();
}
/**
* String 入参
* Integer 进度
* Boolean 返回值
*/
public static class DownloadAsyncTask extends AsyncTask<String, Integer, Boolean> {
String mUrl;
String mFilePath;
OnDownloadListener mListener;
public DownloadAsyncTask(String mUrl, String mFilePath, OnDownloadListener mListener) {
this.mUrl = mUrl;
this.mFilePath = mFilePath;
this.mListener = mListener;
}
/**
* 在异步任务之前,在主线程中
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
//可操作UI 类似淘米,之前的准备工作
if(mListener != null){
mListener.onStart();
}
}
/**
* 在另外一个线程中处理事件
*
* @param params 入参 煮米
* @return 结果
*/
@Override
protected Boolean doInBackground(String... params) {//String... strings表示长度是可变参数,
String apkUrl = mUrl;
try {
//构造URL
URL url = new URL(apkUrl);
//构造连接,并打开
URLConnection urlConnection = url.openConnection();
InputStream inputStream =urlConnection.getInputStream();
//获取下载内容的总长度
int contentlength = urlConnection.getContentLength();
//对下载地址进行处理
File apkFile = new File(mFilePath);
if(apkFile.exists()){
boolean result = apkFile.delete();
if(!result){ //如果失败了
if(mListener != null){
mListener.onFail(-1,apkFile,"文件删除失败");
}
return false;
}
}
//已下载的大小 已下载大小/总长度*100等于下载进度
int downloadSize = 0;
//byte数组
byte[] bytes = new byte[1024];
int length;
//创建一个输入管道
OutputStream outputStream = new FileOutputStream(mFilePath);
length = inputStream.read(bytes);
//不断的一车一车挖土,直到挖不倒为止
while ((length = inputStream.read(bytes))!= -1){
//挖到的放到我们的文件管道里
outputStream.write(bytes,0,length);
//累加我们的大小
downloadSize += length;
//发送进度
publishProgress(downloadSize*100/contentlength);
}
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
if(mListener != null){
mListener.onFail(-2,new File(mFilePath),e.getMessage());
}
return false;
}
if(mListener != null){
mListener.onSuccess(0,new File(mFilePath));
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
//也是在主线程中,执行结果处理
if (mListener != null){
if(result){
mListener.onSuccess(0,new File(mFilePath));
}else {
mListener.onFail(-1,new File(mFilePath),"下载失败");
}
}
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//收到进度,然后处理:也是在UI线程中
if(values!=null&&values.length>0){
if(mListener != null){
mListener.onProgress(values[0]);
}
}
}
}
public interface OnDownloadListener{
void onStart();
void onSuccess(int code,File file);
void onFail(int code,File file,String message);
void onProgress(int progress);
/**
* 如果加写下面这个子类实现了OnDownloadListener的抽象方法,则外部创建该接口时,如通过
* new DownloadHelper.OnDownloadListener.SimpleDownloadListener()调用该方法时,
* 不需要每次都重写已在SimpleDownloadListener类中实现的onStart()和onProgress()这两个方法
*/
abstract class SimpleDownloadListener implements OnDownloadListener{
@Override
public void onStart() {
}
@Override
public void onProgress(int progress) {
}
}
}
}
外部调用
MainActivity.java
package com.administrator.asynctaskdemo;
import android.os.AsyncTask;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.w3c.dom.Text;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.time.LocalDate;
/**
* 1.网络上请求数据:申请网络权限 读写存储权限
* 2.布局我们的layout
* 3.下载之前我们要做什么? UI
* 4.下载中我们要做什么? 数据
* 5.下载后我们要做什么? UI
*/
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";//键盘在空白处输入logt,AndroidStudio会快速生成这行代码
public static final String APK_URL = "http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk";
private ProgressBar mProgressBar;
private Button mDownloadButton;
private TextView mResultTextView;
private int INIT_PROGRESSBAR;
private String FILE_NAME = "XueXi.apk";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化视图
initView();
//设置点击监听
setListener();
//初始化UI数据
setData();
}
private void setListener() {
mDownloadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//TODO 18/5/10 下载任务
DownloadHelper.download(APK_URL," ", new DownloadHelper.OnDownloadListener.SimpleDownloadListener() {
@Override
public void onSuccess(int code, File file) {
Log.e("TAG",String.valueOf(code));
}
@Override
public void onFail(int code, File file, String message) {
Log.e("TAG",String.valueOf(code));
Log.e("TAG",message);
}
});
}
});
}
private void setData() {
mProgressBar.setProgress(INIT_PROGRESSBAR);
mDownloadButton.setText("点击下载");
mResultTextView.setText("准备下载");
}
/**
* 初始化视图
*/
private void initView() {
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mDownloadButton = (Button) findViewById(R.id.button);
mResultTextView = (TextView) findViewById(R.id.textView);
}
}