Android开发高级进阶(二)—多线程(实现简单下载器)

AsyncTask

AsyncTask适用于简单的异步处理,不需要借助线程和Handler即可实现。

AsyncTask

使用AsyncTask的步骤:

创建AsyncTask的子类,并为三个泛型参数指定类型。如果某个泛型参数不需要指定类型,则可将它指定为void。

根据需要实现以下方法:

  • doInBackground(Params…):后台线程将要完成的任务。该方法可以调用
  • publishProgress(Progress… values)方法更新任务的执行进度。
  • onProgressUpdate(Progress… values):在doInBackground()方法中调用publishProgress()方法更新任务的执行进度后,将会触发该方法。
  • onPreExecute():该方法将在执行后台耗时操作前被调用。通常用于完成一些初始化准备工作。
  • onPostExecute(Result result):当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground()方法的返回值传给该方法。

调用AsyncTask子类的实例的execute(Params… params)开始执行耗时任务。
这里通过实现一个简单的下载器来学习AsyncTask。

这个下载器就一个界面,包含一个输入框,用来输入下载地址,一个按钮,用来开始下载。

界面代码如下:activity_download.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
tools:context="com.trampcr.downloaddemo.MainActivity">

<EditText
    android:id="@+id/et_url"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"
    android:hint="请输入下载地址" />

<Button
    android:id="@+id/btn_start_download"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/et_url"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="50dp"
    android:background="@drawable/button_style"
    android:text="开始下载"
    android:textColor="#000000" />

</RelativeLayout>

里是自定义按钮的形状。代码如下:button_style.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:topLeftRadius="10dp"
    android:radius="8dp"
    android:topRightRadius="10dp"
    android:bottomLeftRadius="10dp"
    android:bottomRightRadius="10dp" />
<stroke android:color="#000000"
    android:width="0.7dp"/>
</shape>

根据上面的步骤,第一步是实现AsyncTask的子类,代码如下:DownloadAsyncTask.java

public class DownloadAsyncTask extends AsyncTask<URL, Integer, String> {

private ProgressDialog progressDialog;
private int hasRead = 0;
private Context context;

public DownloadAsyncTask(Context context) {
    this.context = context;
}

@Override
protected String doInBackground(URL... params) {
    try {
        URLConnection urlConnection = params[0].openConnection();
        InputStream inputStream= urlConnection.getInputStream();
        String downloadFolderName = Environment.getExternalStorageDirectory() + File.separator + "trampcr" + File.separator;
        File file = new File(downloadFolderName);
        if (!file.exists()){
            file.mkdir();
        }
        String fileName = downloadFolderName + "zxm.apk";
        File apkFile = new File(fileName);
        if (apkFile.exists()) {
            apkFile.delete();
        }
        byte[] buff = new byte[1024];
        int length = 0;
        OutputStream outputStream = new FileOutputStream(fileName);
        while ((length = inputStream.read(buff)) != -1) {
            outputStream.write(buff, 0, length);
            hasRead++;
            publishProgress(hasRead);
        }
        outputStream.close();
        inputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    progressDialog.dismiss();
    Toast.makeText(context, "下载完成", Toast.LENGTH_LONG).show();
}

@Override
protected void onPreExecute() {
    super.onPreExecute();
    progressDialog = new ProgressDialog(context);
    //设置对话框标题
    progressDialog.setTitle("任务正在进行中");
    //设置对话框显示的内容
    progressDialog.setMessage("正在下载,请稍等...");
    //设置对话框的取消按钮
    progressDialog.setCancelable(true);
    //设置进度条的最大值
    progressDialog.setMax(2000);
    //设置进度条风格
    progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    //设置对话框的进度条是否显示进度
    progressDialog.setIndeterminate(false);
    progressDialog.show();
}

@Override
protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
    //更新进度
    progressDialog.setProgress(values[0]);
   }
}

这里在onPreExecute()方法中实现了初始化并显示进度对话框,在doBackground()方法通过读文件、写文件完成下载任务,并调用publishProgress()方法发出更新进度,在onProgressUpdate()方法中执行更新进度,在onPostExecute()方法中销毁进度条对话框,并弹出Toast提示下载完成。

DownloadActivity.java

public class DownloadActivity extends AppCompatActivity implements View.OnClickListener{

//    public static final String DOWNLOAD_URL = "http://psoft.33lc.com:801/small/rootexplorer_33lc.apk";
private Button mBtnStartDownload;
private EditText mEtUrl;
private String mUrl;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_download);

    mEtUrl = (EditText) findViewById(R.id.et_url);
    mBtnStartDownload = (Button) findViewById(R.id.btn_start_download);

    mBtnStartDownload.setOnClickListener(this);
}

@Override
public void onClick(View v) {
    mUrl = mEtUrl.getText().toString().trim();
    DownloadAsyncTask downloadAsyncTask = new DownloadAsyncTask(DownloadActivity.this);
    try {
//            downloadAsyncTask.execute(new URL(DOWNLOAD_URL));
        downloadAsyncTask.execute(new URL(mUrl));
    } catch (MalformedURLException e) {
        e.printStackTrace();
        }
     }
}

上一步实现了AsyncTask的子类,这一步就需要创建该子类的实例,并执行execute()开始执行任务。

所需要的权限:

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

效果图如下:

文/trampcr(简书作者)
原文链接:http://www.jianshu.com/p/6a558a23084a
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值