美文网首页
Android使用AsyncTask完成一个简单的下载进度条

Android使用AsyncTask完成一个简单的下载进度条

作者: 番茄tomato | 来源:发表于2020-05-27 10:54 被阅读0次

    参考文章:https://www.jianshu.com/p/ee1342fcf5e7
    这是一个使用AsyncTask完成的模拟下载进度条:

    模拟下载进度条
    MainActivity布局如下:非常简单,就是button,textview,progressbar,button从上到下排列
        <Button
            android:id="@+id/startBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="Start"
            />
    
        <TextView
            android:id="@+id/downloadHintText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="等待开始下载数据"
            />
        <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:max="100"
            android:progress="0" />
        <Button
            android:id="@+id/cancelBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="cancel"
            />
    

    然后是DownloadTask代码,这里需要继承于AsyncTask,并确定三个范形:

    //第一个参数是执行异步操作传入的参数 Unit表示不需要参数
    //第二个参数是进度条表示
    //第三个参数是异步操作结束后 返回的参数 这里是布尔型表示是否成功
    class DownloadTask() : AsyncTask<Unit, Int, Boolean>() {
        private var TAG = "下载任务"
        //控制界面
        var progressBar: ProgressBar? = null
        var downloadHint:TextView?=null
        var context: Context? = null
        //进度条最大长度
        var progressBarMax=10000
        override fun onPreExecute() {
            super.onPreExecute()
            //异步操作执行之前 可以显示加载框等操作
    
            downloadHint?.text="准备开始下载"
        }
    
        override fun doInBackground(vararg params: Unit?): Boolean {
            //后台线程执行的内容
            //执行完毕后 返回内容
            return try {
    
                startDownload()//开始下载
                true//下载成功没有出错 则返回true表示下载成功
            } catch (e: Exception) {
                false//下载出错则返回false表示下载失败
            }
        }
    
        override fun onProgressUpdate(vararg values: Int?) {
            //更新显示进度条进度
            super.onProgressUpdate(*values)
            Log.d(TAG, "显示进度: ${values[0].toString()}")
    
            //这里将进度以百分数的形势表示出来
            val df = DecimalFormat("0.00")
            var hintContent= ((values[0]?.toDouble())?.div(progressBarMax))?.times(100)
            downloadHint?.text="下载中,进度${df.format(hintContent)}%"
    
            //设置最大长度 并显示进度条
            progressBar?.max=progressBarMax //最大长度10000 显示内容就是 12-->0.12%
            progressBar?.progress = values[0] ?: 0//需要捕捉空指针 如果是空就显示0
    
        }
    
        override fun onPostExecute(result: Boolean?) {
            //执行完毕 可以隐藏关闭进度条
            super.onPostExecute(result)
            if(result!!){
                downloadHint?.text="下载完成"
            }else{
                downloadHint?.text="下载失败"
            }
        }
    
            //调用cancel后 这个方法会被执行
        override fun onCancelled() {
            super.onCancelled()
           downloadHint?.text="下载取消"
        }
    
    
        //在这个方法中进行下载并计算加载进
        private fun startDownload() {
            Log.d(TAG, "开始下载")
            var progress:Int=0
            var fileSize:Double =0.0//下载中的文件
            var allFileSize :Double= 10000.0//总共需要下载的文件大小
    
            while (true) {
                if(isCancelled){break}//在循环中 任务被取消 就退出
    
                sleep(1)//控制下载速度 1毫秒下载1个单位
                fileSize += 1
                progress= ((fileSize/allFileSize)*progressBarMax).toInt()
    
                publishProgress(progress)
    
                if (fileSize >= allFileSize) {
                    break
                }
            }
        }
    }
    

    接下来就是在MainActivity中让DownloadTask跑起来:

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            var downloadTask=DownloadTask()
            //绑定View
            downloadTask.progressBar=progressBar//要动态修改的加载框
            downloadTask.context=this//传入上下文 可以在downloadTask中显示toast
            downloadTask.downloadHint=downloadHintText
            startBtn.setOnClickListener {
                //task智能被执行一次 再次点击会崩溃 这里可以做好判断
                downloadTask.execute()
            }
            cancelBtn.setOnClickListener {
                //点击取消
                downloadTask.cancel(true)
            }
        }
    }
    

    代码非常简单,注释也写的很清楚,就不一一说明了。
    这里提几个注意点:

    1. downloadTask.execute()

    这个方法只能被执行一次,再次执行会报错,所以在点击下载按钮时可以进行一下判断

    2.downloadTask.cancel(true)

    https://www.cnblogs.com/xqxacm/p/5227159.html
    执行这个方法后,onCancelled()会很快的被调用,这里可以修改ui提示任务终止,但是其实任务并没有停下,只是isCancelled被标记为true了,想让任务真正的停下,需要增加具体的逻辑判断

            while (true) {
                if(isCancelled){break}//在循环中 任务被取消 就退出
                 .....
            }
    

    为了避免界面销毁后任务仍然进行,可以在界面生命周期onDestroy中调用cancel(true)

    3.计算和显示百分比下载进度

    下载进度=已下载的文件大小/总文件大小 //例如等于0.5
    但是progressBar只能使用整数表示进度,例如进度条总大小progressBarMax=10000,进度progress就是1~10000
    所以需要将刚刚计算出的0.5乘以progressBarMax得到进度progress=5000
    这时候就是progressBar就刚好进行到一半了。

    但是这里还在需要在上方显示 50.00% 文字提示,直接根据progress=5000和progressBarMax=10000计算即可,相处得0.5,再乘100,加上“%”,不就是50%了。
    但其实错了,在Kotlin和JAVA中,Int之间的运算只能得Int。Int相除有小数时直接舍弃掉小数点后的部分,所以这里progress/progressBarMax=0,需要将其中一个使用toDouble()方法转化为Double数据,再计算得0.50000000,然后乘100得50.0000000,保留两位小数加上百分号:50.00%

            //这里将进度以百分数的形势表示出来
            val df = DecimalFormat("0.00")//保留两位小数
            var hintContent= ((values[0]?.toDouble())?.div(progressBarMax))?.times(100)
            downloadHint?.text="下载中,进度${df.format(hintContent)}%"
    
    4.注意一些非空判断

    这里是手动绑定view,注意非空判断,还有进度数值等其他地方,就不一一举例了

    相关文章

      网友评论

          本文标题:Android使用AsyncTask完成一个简单的下载进度条

          本文链接:https://www.haomeiwen.com/subject/cuoiahtx.html