一、定义:
Android UI线程是不安全的,如果想在子线程进行UI操作,就要用到Android的异步消息处理机制,除了Handler之外,还有一个AsyncTask也能够实现。
二、AsyncTask用法
2.1、三个参数
要使用AsyncTask首先创建一个类,并继承它,同时需要指定他的三个泛型参数。
public class DownloadAsyncTask extends AsyncTask<Void, Integer, Integer> { }
1、Params(Void)
在执行后台任务时需要传入的参数。
2、Progress(Integer)
后台任务需要向外传递任务进程时的参数类型。
3、Result(Integer)
后台任务执行完,需要提交给UI线程所处理的数据类型。
当然这三个参数如果有不需要的可以定义为Void。
2.2 四个方法
- Void onPreExecute()
在执行后台任务之前,需要再UI线程中进行的一些设置操作,比如初始化ProgressBar等。
- doInBackground()
执行后台耗时任务。
- Void onProgressUpdate()
当后台任务执行过程中需要向外传递任务进度时,通过调用publishProgress()即可将进程参数传递给此方法。一般在此方法中进行任务进度的显示的相关操作。
- onPostExecute()
将后台任务结束后传递出来的参数在此方法中进行UI界面的更新操作。
三、实例参考
本例实现了将一段网络视频下载到手机SD卡上的任务。
package com.example.pc.externalstoragetest; import android.annotation.SuppressLint; import android.os.AsyncTask; import android.os.Environment; import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; /** * Created by pc on 2018/6/6. */ public class DownloadAsyncTask extends AsyncTask<Void, Integer, Integer> { private ProgressBar pb; private TextView showProgressNub; public DownloadAsyncTask(ProgressBar pb,TextView showProgressNub) { this.pb = pb; this.showProgressNub=showProgressNub; } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Integer doInBackground(Void... voids) { //在SD卡上新建一个名叫:dahuangfeng.mp4的文件 File f=new File(Environment.getExternalStorageDirectory(),"dahuangfeng.mp4"); //如果不存在则创建 if(!f.exists()){ try { f.createNewFile(); //获取该文件的输出流 OutputStream os=new FileOutputStream(f); //创建一个URL的网络视频连接 URL url=new URL("http://vt1.doubanio.com/201806051925/5a95ce9e62a5473be84dfbaa1b69302b/view/movie/M/402300072.mp4"); //通过URL.openConnection()获取 HttpURLConnection HttpURLConnection conn= (HttpURLConnection) url.openConnection(); //设置请求方法为GET conn.setRequestMethod("GET"); //设置请求时间 conn.setReadTimeout(5000); //获取输入流 InputStream is=conn.getInputStream(); //获取文件总大小 long total_lenth=conn.getContentLength(); //读取输入流中的数据,并写入到SD卡dahuangfeng.mp4的文件中 byte[] b=new byte[1024]; int length=0; int current_lenth=0; while((length=is.read(b))!=-1){ os.write(b,0,length); //当前已读文件的大小 current_lenth+=length; //获取当前进度 float progress= (current_lenth/(float)total_lenth)*100000; int value= (int) progress; //将进度数据传递给UI线程 publishProgress(value); } System.out.println("..........下载结束....."); os.flush(); is.close(); os.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } return null; } @SuppressLint("NewApi") @Override protected void onProgressUpdate(Integer... values) { pb.setMax(100); pb.setMin(0); //设置progressBar的当前进度 pb.setProgress(values[0]); pb.setVisibility(View.VISIBLE); //在Textview中显示进度数字 showProgressNub.setText(pb.getProgress()+"%"); super.onProgressUpdate(values); } @Override protected void onPostExecute(Integer file) { super.onPostExecute(file); } }
效果图
录制软件有点问题,应该是点击按钮,就会立即下载。