Android中通过AsyncTask类来制作炫酷进度条的实例教程

 更新时间:2016年05月06日 17:59:30   作者:ALIOUS  
这篇文章主要介绍了Android中通过AsyncTask来制作炫酷进度条的实例教程,借助AsyncTask类的线程操作方法来管理异步任务,需要的朋友可以参考下

AsyncTask (API level 3,所以几乎所有目前在市面上流通的 Android 版本皆可使用)
是除 Thread 外的另一种选择,Android 团队鼓励主执行绪(UI thread) 专注于操作 & 画面的流畅呈现,
其余工作 (如网络资料传输、档案/磁碟/资料存取) 最好都在背景执行;
Thread 通常要搭配 Handler 使用,而 AsyncTask 用意在简化背景执行 thread 程序码的撰写。

如果您预期要执行的工作能在几秒内完成,就可以选择使用 AsyncTask,若执行的时间很长,
Android 则强烈建议采用 Executor, ThreadPoolExecutor and FutureTask。

要使用 AsyncTask,必定要建立一个继承自 AsyncTask 的子类别,并传入 3 项资料:

  • Params -- 要执行 doInBackground() 时传入的参数,数量可以不止一个
  • Progress -- doInBackground() 执行过程中回传给 UI thread 的资料,数量可以不止一个
  • Rsesult -- 传回执行结果

若您没有参数要传入,则填入 Void (注意 V 为大写)。

AsyncTask 的运作有 4 个阶段:

  • onPreExecute -- AsyncTask 执行前的准备工作,例如画面上显示进度表,
  • doInBackground -- 实际要执行的程序码就是写在这里,
  • onProgressUpdate -- 用来显示目前的进度,
  • onPostExecute -- 执行完的结果 - Result 会传入这里。

除了 doInBackground,其他 3 个 method 都是在 UI thread 呼叫


炫酷进度条实例
我们以一个实例来说明,“点击按钮开始下载QQAndroid安装包,然后显示一个对话框来反馈下载进度”。我们先初始化一个对话框,由于要显示进度,我们用Github上面一个能够显示百分比的进度条 NumberProgressbar,启动任务的按钮我们使用 circlebutton,一个有酷炫动画的按钮,Github上面有很多非常好的开源项目,当然炫酷的控件是其中一部分了,后面有机会,会去学习一些比较流行的控件它们的实现原理,今天就暂且拿来主义了~~。

1.先初始化进度条提示对话框。

 builder = new AlertDialog.Builder(
     MainActivity.this);
 LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
 mDialogView = inflater.inflate(R.layout.progress_dialog_layout, null);
 mNumberProgressBar = (NumberProgressBar)mDialogView.findViewById(R.id.number_progress_bar);
 builder.setView(mDialogView);
 mDialog = builder.create();

2.设置按钮点击事件。

 findViewById(R.id.circle_btn).setOnClickListener(new View.OnClickListener(){
   @Override
   public void onClick(View v) {
     dismissDialog();
     mNumberProgressBar.setProgress(0);
     myTask = new MyAsyncTask();
     myTask.execute(qqDownloadUrl);
   }
 });

3.DownloadAsyncTask实现,有点长。

private class DownloadAsyncTask extends AsyncTask<String , Integer, String> {

 @Override
 protected void onPreExecute() {
   super.onPreExecute();
   mDialog.show();

 }

 @Override
 protected void onPostExecute(String aVoid) {
   super.onPostExecute(aVoid);
   dismissDialog();
 }

 @Override
 protected void onProgressUpdate(Integer... values) {
   super.onProgressUpdate(values);

   mNumberProgressBar.setProgress(values[0]);
 }

 @Override
 protected void onCancelled(String aVoid) {
   super.onCancelled(aVoid);
   dismissDialog();
 }

 @Override
 protected void onCancelled() {
   super.onCancelled();
   dismissDialog();
 }

 @Override
 protected String doInBackground(String... params) {
   String urlStr = params[0];
   FileOutputStream output = null;
   try {
     URL url = new URL(urlStr);
     HttpURLConnection connection = (HttpURLConnection)url.openConnection();
     String qqApkFile = "qqApkFile";
     File file = new File(Environment.getExternalStorageDirectory() + "/" + qqApkFile);
     if (file.exists()) {
       file.delete();
     }
     file.createNewFile();
     InputStream input = connection.getInputStream();
     output = new FileOutputStream(file);
     int total = connection.getContentLength();
     if (total <= 0) {
       return null;
     }
     int plus = 0;
     int totalRead = 0;
     byte[] buffer = new byte[4*1024];
     while((plus = input.read(buffer)) != -1){
       output.write(buffer);
       totalRead += plus;
       publishProgress(totalRead * 100 / total);
       if (isCancelled()) {
         break;
       }
     }
     output.flush();
   } catch (MalformedURLException e) {
     e.printStackTrace();
     if (output != null) {
       try {
         output.close();
       } catch (IOException e2) {
         e2.printStackTrace();
       }
     }
   } catch (IOException e) {
     e.printStackTrace();
     if (output != null) {
       try {
         output.close();
       } catch (IOException e2) {
         e2.printStackTrace();
       }
     }
   } finally {
     if (output != null) {
       try {
         output.close();
       } catch (IOException e) {
         e.printStackTrace();
       }
     }
   }
   return null;
 }
}

这样一个简单的下载文件文件就基本实现了,到目前为止谈不上技巧,但是现在我们有一个问题,就是如果我们的Activity正在后台执行一个任务,可能耗时较长,那用户可能会点击返回退出Activity或者退出App,那么后台任务不会立即退出,如果AsyncTask内部有Activity中成员变量的引用,还会造成Activity的回收延时,造成一段时间内的内存泄露,所以我们需要加上下面的第四步处理。

4.onPause中判断应用是否要退出,从而决定是否取消AsyncTask执行。

@Override
protected void onPause() {
 super.onPause();
 if (myTask != null && isFinishing()) {
   myTask.cancel(false);
 }
}

这样我们的异步任务就会在Activity退出时,也随之取消任务执行,顺利被系统销毁回收,第四步很多时候会被遗漏,而且一般也不会有什么致命的问题,但是一旦出问题了,就很难排查,所以遵循编码规范还是有必要的。


相关文章

  • 利用Android封装一个有趣的Loading组件

    利用Android封装一个有趣的Loading组件

    这篇文章我们将利用Android封装一个可以自定义配置前景色和背景色的Loading组件,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-08-08
  • android studio项目:绑定服务和线程实现计时器

    android studio项目:绑定服务和线程实现计时器

    这篇文章主要介绍了android studio项目:绑定服务和线程实现计时器,完成一个秒表,具备启停功能,通过绑定服务实现功能,通过Thread+handler更新界面,需要的朋友可以参考一下
    2021-12-12
  • AndroidStudio:手势识别

    AndroidStudio:手势识别

    这篇文章主要介绍了AndroidStudio手势识别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • Android中使用Gradle来构建App项目的入门指南

    Android中使用Gradle来构建App项目的入门指南

    Gradle是Java世界中一个高人气自动化构建工具,在安卓开发领域同样备受追捧,这里为大家带来Android中使用Gradle来构建App项目的入门指南,来看看Gradle的作用与基本结构.
    2016-06-06
  • Android基于Flutter编写文件下载管理器

    Android基于Flutter编写文件下载管理器

    文件下载在很多类型的应用中会涉及,例如音乐、文档、包括图片(只是图片可以使用一些组件完成无感知的下载)。本篇介绍使用Flutter中的Dio下载方法完成文件的下载,需要的可以参考一下
    2022-03-03
  • Android APP数字解锁实例详解

    Android APP数字解锁实例详解

    这篇文章主要介绍了Android 应用数字解锁实例详解的相关资料,这里附有实例代码及实现效果图,需要的朋友可以参考下
    2016-11-11
  • Android中RecyclerView实现商品分类功能

    Android中RecyclerView实现商品分类功能

    这篇文章主要为大家详细介绍了Android中RecyclerView实现商品分类功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • Android ndk获取手机内部存储卡的根目录方法

    Android ndk获取手机内部存储卡的根目录方法

    今天小编就为大家分享一篇Android ndk获取手机内部存储卡的根目录方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • 详解OkSocket与Android的简单使用

    详解OkSocket与Android的简单使用

    本篇文章主要介绍了详解OkSocket与Android的简单使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Android获取当前位置的经纬度数据

    Android获取当前位置的经纬度数据

    这篇文章主要介绍了Android获取当前位置的经纬度数据的相关资料,需要的朋友可以参考下
    2016-02-02

最新评论