背景:
在Android中实现异步任务机制有两种方式:Handle和AsycnTask
在Handle模式中,需要为每一个异步任务创建一个新的线程,任务完成后通过Handel实例setMessage向UI线程发送消息,完成UI界面的更新.这种方式对于整个过程而言,控制比较精细,结构相对清晰,但是代码相对复杂,当有多个异步任务同时执行时,不易对线程进行精确的控制.
为了简化操作,官方提供工具类android.os.AsyncTask,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务。
定义一个AsycnTask:
static class MyAsycnTask extends AsyncTask<String,Integer,Boolean>{}
它的参数是泛型,分别代表"启动任务时传入的参数","后台任务执行的进度","执行完成后返回结果类型",当然如果你不需要使用,可以使用void代替.
定义AsycnTask;必须重写protected Boolean doInBackground(String... strings)用于执行后台任务
public static class MyAsycnTask extends AsyncTask<String,Integer,String> { //异步任务执行前的准备工作 UI线程 @Override protected void onPreExecute() { super.onPreExecute(); } //执行异步任务 子线程 @Override protected String doInBackground(String... strings) { return null; } //异步任务完成后执行 UI线程 @Override protected void onPostExecute(String s) { super.onPostExecute(s); } //更新后台任务进度 UI线程 @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } //当任务取消时执行 @Override protected void onCancelled(String s) { super.onCancelled(s); } }
Demo:实现异步下载操作,并更新进度,以及取消下载任务
public class MainActivity extends AppCompatActivity { protected static TextView textView; protected Button button1; protected Button button2; protected static ProgressBar progressBar; protected MyAsycnTask myasycnTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //调用execute触发异步任务执行 myasycnTask = new MyAsycnTask(); myasycnTask.execute(); } }); findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //调用cancel,取消线程任务 myasycnTask.cancel(false); textView.setText("已暂停下载"); } }); initView(); } public void initView() { textView = findViewById(R.id.textView); button1 = findViewById(R.id.button); button2 = findViewById(R.id.button2); progressBar = findViewById(R.id.progressBar); } static class MyAsycnTask extends AsyncTask<String, Integer, Boolean> { //下载前的准备 UI线程 @Override protected void onPreExecute() { super.onPreExecute(); textView.setText("正在下载中"); progressBar.setProgress(0); } //开始下载任务 子线程 @Override protected Boolean doInBackground(String... strings) { try { if (!isCancelled()) { URL url = new URL("https://clfile.imooc.com/class/assist/119/4289211/Handler%E6%BA%90%E7%A0%81(%E4%BB%A3%E7%A0%81%E7%BB%8F%E8%BF%87%E5%B0%81%E8%A3%85).rar"); URLConnection connection = url.openConnection(); InputStream inputStream = connection.getInputStream(); //获取文件总长度 int fileContent = connection.getContentLength(); //设置文件夹路径 String fileName = Environment.getExternalStorageDirectory() + File.separator + "2018.7.27"; File file = new File(fileName); if (file.exists()) { file.delete(); } //文件已下载长度 int fileLength = 0; int len = 0; byte[] b = new byte[1024]; OutputStream outputStream = new FileOutputStream(fileName); while ((len = inputStream.read(b)) != -1) { outputStream.write(b, 0, len); fileLength += len; publishProgress(fileLength * 100 / fileContent); } inputStream.close(); outputStream.close(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return true; } //下载完成后执行的操作 UI线程 @Override protected void onPostExecute(Boolean aBoolean) { super.onPostExecute(aBoolean); textView.setText("下载完成" + aBoolean); } //更新后台进度 UI线程 @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); if (values != null && values[0] > 0) { progressBar.setProgress(values[0]); } } } }
获取权限:manifests
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
效果图展示:
注意事项:
1.异步任务的实例必须在UI线程中创建
2.execute方法必须在UI线程中调用
3.不要手动的调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。
4.不能在doInBackground(Params... params)中修改UI信息
5.一个任务实例只能执行一次,如果执行第二次则会抛出异常
6.当有多个任务需要执行性时,按顺序一个一个执行