AsyncTask的简单使用

为了更加方便对UI的操作,Android提供了AsyncTask,借助AsyncTask可以简单的从子线程切换到
主线程。

  • 参数解释:
    1、Params:这是一个任务参数,一般我们会定义成String类型的,例如要获取网络资源的URL地址
    2、Progress:任务执行的刻度,一般我们会定义成Integer类型
    3、Result:返回结果类型,本例为Integer
  • 需要实现的方法
    1、onPreExecute:这是一个预处理方法,在任务开始的时候执行,我们可以在这里进行一些控件的实例化,设置属性等。
    2、doInBackground:这是一个任务操作方法,也是最重要的一个方法,所有的耗时操作都应该在这里执行。不能再次方法中进行UI操作
    3、onProgressUpdate:这是一个进度即时更新方法,在这里我们可以即时更新任务滚动条的进度, 当在doInBackground里调用publishProgress时触发。
    4、onPostExecute:这是一个任务结果处理方法,在doInBackground里执行完任务,会将结果通知给这个类,在这类中我们可以对UI进行更新操作。
  • 以上方法的执行顺序

onPreExecute–>doInBackground–>onProgressUpdate–>onPostExecute

  • 样例:
    布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    >

    <Button
        android:id="@+id/download"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="下载"
        />

</LinearLayout>
  • MyAsyncTask继承AsyncTask
package com.example.downloading;

import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.widget.ImageView;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import java.io.InputStream;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MyAsyncTask extends AsyncTask<String,Integer, Integer> {
    private ProgressDialog progressDialog;
    public MyAsyncTask(ProgressDialog progressDialog){
        this.progressDialog = progressDialog;
    }

//    进行界面的初始化操作,如进度条的显示
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog.setTitle("当前任务");
        progressDialog.setMessage("正在下载图片,请稍等....");
//        设置进度条进度
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.show();
    }

//    在这里处理耗时任务,任务完成后通过return语句返回任务执行的结果
    @Override
    protected Integer doInBackground(String... strings) {
        InputStream is = null;
        FileOutputStream outputStream = null;
        try{
            String downloadUrl = strings[0];
            String name = downloadUrl.substring(downloadUrl.lastIndexOf("/"));
            String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder().url(downloadUrl).build();
            Response response = client.newCall(request).execute();

            long filesize = response.body().contentLength();
            is = response.body().byteStream();
             byte[] arr = new byte[1024];
             int len;
             int total = 0;
             outputStream = new FileOutputStream(fileName + name);
             //可以在手机内存中的DownLoad文件下找到下载的东西
             while((len = is.read(arr)) != -1) {
                 outputStream.write(arr, 0, len);
                 total += len;
                 int values = (int) ((total / (float) filesize) * 100);
                 publishProgress(values); //调用此方法将下载进度传进来,这样就会调用onProgressUpdate()方法,进行UI操作

             }
             response.body().close();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if(outputStream != null){
                    outputStream.close();
                }
                if(is != null){
                    is.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return 1;
    }

//    实时UI更新操作,被UI线程所调用 在这里可以即时更新(如进度条进度)
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

        progressDialog.setProgress(values[0]);
    }
//在这里会返回doInBackground的操作结果,被UI线程调用,更新最后UI结果,执行任务的收尾工作
    @Override
    protected void onPostExecute(Integer integer) {
        super.onPostExecute(integer);
        progressDialog.dismiss();
    }
}

MainActivity

package com.example.downloading;

import androidx.appcompat.app.AppCompatActivity;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    ProgressDialog progressDialog;
    ImageView imageView;
    Button download;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        download = findViewById(R.id.download);
        progressDialog = new ProgressDialog(this);
        //这里的path随自己的需求而改变,这里放的是一张图片的地址
        final String path = "http://y.gtimg.cn/music/photo_new/T002R180x180M000003c616O2Zlswm.jpg";
        download.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MyAsyncTask myAsyncTask = new MyAsyncTask(progressDialog);
                myAsyncTask.execute(path);
            }
        });
    }
}
  • 注意,在我自己手机上运行时需要添加:
android:usesCleartextTraffic="true"

添加权限:

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

还需要自己手动在手机的设置上面开启存储权限