使用异步任务的原因就是因为:Android是单线程模型 ,耗时操作在非主线程中运行,而UI更新要在主线程中进行
实现异步的方式有两种。第一种是通过AsyncTask来实现,第二种是通过线程池或者多线程来实现
AsyncTask只是封装了线程跳转的逻辑,并且能够在子线程中处理 耗时操作,从而提高程序整体的运行效率,UI的更新还是在主线程中的
异步任务的中构建四个方法,分别是onPreExecute() 操作前的准备工作,doInBackground()耗时操作,onProgressUpadate()更新进度,onPostExcute()执行完操作后更新UI显示结果
AsyncTask常用方法详解
package com.example.testapplication;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
/**
* 1. 网络上请求数据:申请网络权限 读写存储权限
* 2.布局
* 3.下载之前我们要做什么
* 4.下载中我们要做什么
* 5.下载后我们要做什么?
*
*
* */
public class AsncTaskActivity extends AppCompatActivity {
private static final String TAG = "AsncTaskActivity";
private ProgressBar progressBar;
private Button mDownloadButton;
private TextView mTextView;
private int INIT_PROGRESS;
public static final String APK_URL = "http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk";
String mFilePath;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_imocasnc);
// java 泛型基础(需加强)
// 初始化视图
initView();
// 设置点击监听
setListener();
// 初始化UI数据
setData();
}
private void setData() {
INIT_PROGRESS = 0;
progressBar.setProgress(INIT_PROGRESS);
mDownloadButton.setText(R.string.click_download); // 快捷键 ctrl + enter
mTextView.setText(R.string.download_text);
}
private void setListener() {
mDownloadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// TODO: 2021/12/20 下载任务
DownloadAsncTask asncTask = new DownloadAsncTask();
//asncTask.execute("xxxx","xxxx","xxxxx");
asncTask.execute(APK_URL);
}
});
}
// 初始化
private void initView() {
// 快捷键 ctrl+alt + f
progressBar = (ProgressBar) findViewById(R.id.progressBar);
mDownloadButton = (Button) findViewById(R.id.load_button2);
mTextView = (TextView) findViewById(R.id.load_txt);
}
/**
* String 入参
* Integer 进度
* Boolean 返回值
*
* */
public class DownloadAsncTask extends AsyncTask<String,Integer,Boolean>{
/**
* 在异步任务之前,在主线程中
* */
@Override
protected void onPreExecute() {
super.onPreExecute();
// 可操作UI
mDownloadButton.setText("下载中....");
mTextView.setText("下载中");
progressBar.setProgress(0);
}
// 在另外一个线程中处理事件
@Override
// String... params 表示可变参数
protected Boolean doInBackground(String... params) {
if(params != null && params.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+"imooc.apk";
// 对下载地址进行处理
File apkFile = new File(mFilePath);
if(apkFile.exists()){
boolean result = apkFile.delete();
if(!result){
return false;
}
}
// 已下载的大小
int downloadSize = 0;
// byte 数组
byte[] bytes = new byte[1024];
int length;
// 创建一个输入管道
OutputStream outputStream = new FileOutputStream(mFilePath);
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?"下载完成":"下载失败");
mTextView.setText(result?"下载完成":"下载失败");
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// 收到进度,然后处理: 也是在UI线程中
// 收到进度,然后处理: 也是在UI线程中。
if (values != null && values.length > 0) {
progressBar.setProgress(values[0]);
}
}
}
}
自定义下载的封装思想
package com.imooc.asynctask;
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 renkangke on 16/12/19.
*/
public class DownloadHelper {
public static void download(String url, String localPath, OnDownloadListener listener){
DownloadAsyncTask task = new DownloadAsyncTask(url, localPath, listener);
task.execute();
}
public static class DownloadAsyncTask extends AsyncTask<String, Integer, Boolean> {
String mUrl;
String mFilePath;
OnDownloadListener mListener;
public DownloadAsyncTask(String url, String filePath, OnDownloadListener listener) {
mUrl = url;
mFilePath = filePath;
mListener = listener;
}
/**
* 在异步任务之前,在主线程中
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
// 可操作UI 类似淘米,之前的准备工作
if(mListener != null){
mListener.onStart();
}
}
/**
* 在另外一个线程中处理事件
*
* @param params 入参 煮米
* @return 结果
*/
@Override
protected Boolean doInBackground(String... params) {
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;
}
}
// 已下载的大小
int downloadSize = 0;
// byte数组
byte[] bytes = new byte[1024];
int length;
// 创建一个输入管道
OutputStream outputStream = new FileOutputStream(mFilePath);
// 不断的一车一车挖土,走到挖不到为止
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);
// 也是在主线程中 ,执行结果 处理
}
@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);
abstract class SimpleDownloadListener implements OnDownloadListener{
@Override
public void onStart() {
}
@Override
public void onProgress(int progress) {
}
}
}
}
DownloadHelper.download(APK_URL, "", new DownloadHelper.OnDownloadListener.SimpleDownloadListener() {
@Override
public void onSuccess(int code, File file) {
}
@Override
public void onFail(int code, File file, String message) {
}
@Override
public void onStart() {
super.onStart();
}
@Override
public void onProgress(int progress) {
super.onProgress(progress);
}
});