AsyncTask的详解与服务的结合下载文件例子

本文介绍了如何使用AsyncTask配合Service实现后台下载文件,包括断点续传功能。详细讲解了AsyncTask的使用,File类的构造方法,以及活动和服务之间的通信方式。通过创建前台服务确保下载任务在后台持续运行,同时通过Activity与自定义Binder交互控制下载进程。
摘要由CSDN通过智能技术生成

1. 写在前面

前面一两个月一直在赶需求,不管什么功能先在网上或者github上找到做出来再说,最近半个月没事做,一直在改代码。发现以前项目中的软件更新没做好,刚好看到郭神书里面这文件下载例子用于更新下载不错,让后台下载任务在服务中执行,然后通过activity和服务绑定,使activity和service可以进行通信。并且好好的学习了asyncTask,现在框架用的比较多,很少有机会接触到这个了。这个文件下载比较好的地方一个是可以像QQ样,更新时可以在界面上还可以操作,还有一个是实现了断点下载,可以接着上次没下载完的地方继续下载。效果图如下:
这里写图片描述

2. 学习

a.继承AsyncTask需要指定的三个参数,AsyncTask(params,progress,result),看着api,可以了解他们的含义
这里写图片描述
params:在使用asynctask时需要传入的参数,可以供后台任务使用,可以为void;
progress:后台任务执行时,如果需要在界面上显示当前进度,则使用这里指定的泛型为单位;
result:当后台任务执行完毕时,需要对结果进行返回,这里指定什么泛型就返回什么样的数据类型,比如,这里指定boolean,则后台任务执行完毕返回true或者false;
当然,继承AsyncTask我们经常要重写的几个方法,看api
这里写图片描述

解释过来,onPreExecute():在后台任务之前在ui线程中调用,这一步通常用于设置后台任务,比如展示一个进度条在用户面前;
doInBackground(Params…):(这翻译过来很直观)在onpreExecute()方法一结束,立马在后台线程调用,这一步在后台运行计算,可能需要一段时间,异步任务的参数传递到这一步,这一步的这些计算一定要有返回,并且要将这些返回结果返回到最后一步。这一步同样是可以使用publishProgress(Progress…)这个方法去发布一个或多个单元的进度,这些值被发布在ui线程的 onProgressUpdate(Progress…) 这一步中;
onProgressUpdate(Progress…):当publishProgress(Progress…)被使用后,被调用在ui线程,执行的时间是不能确定的,这个方法用与在后台任务一直被执行时,展示在用户面前的进度,它能够被用于带动画的进度条或者文本log;
onPostExecute(Result): 被调用在ui线程,当后台任务计算完成,后台任务计算的结果被用来当做参数在这一步中;
b. 有关File这个类的一些构造方法。郭神在保存下载文件时是将它保存在公共下载目录下,我搞错了一个地方所以对他获取file对象的方法很不理解。网上也查不到自己想要的答案,后面在api中看了了File的构造方法。
这里写图片描述
c. 活动和服务通信。在活动中控制服务。通过在service中继承Binder写个自己的Binder类,里面写上自己想要在活动中调用的方法。同时注意在service中重写的onBind()中返回我们自己的Binder对象。然后在活动中 创建ServiceConnection的匿名类,在里面重写onServiceConnected()方法和onServiceDisconnected()方法,这两个方法会在活动和服务成功绑定和断开时调用。并且在onServiceConnected()方法中,获得自己的Binder对象,这样子就可以在活动中想调用Binder中的方法就调用什么方法了。

3. 代码

a.

DownloadTask extends AsyncTask<String,Integer,Integer>,

在选择了这样三种参数,即我们传入String类型参数供后台任务使用,用Integer来表示后台任务的进度,后台任务返回的是Integer类型,这样的的返回值就是我们在onPostExecute()方法中的参数。
这里没有使用onPreExecute()方法,所以在执行这个asynctask直接从后台任务开始。

   @Override
    protected Integer doInBackground(String... params) {

        InputStream is = null;
        RandomAccessFile savedFile = null ;
        File file = null;
        try {
            long downloadFileLength = 0; //记录已下载的文件长度
            String downloadUrl = params[0];
            String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));
            //--->  /storage/emulated/0/Download
            String directroy = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
            Log.i(TAG, "directroyPath--->" + directroy);
            file = new File(directroy+fileName);
            if(file.exists()){  //存在,拿到这个文件已经下载的长度,从这里开始下载
                downloadFileLength = file.length();
            }
            //获得这个下载文件的总长度,使用okhttp
            long contentLength = getContentLength(downloadUrl);
            if(contentLength==0){
  //url地址文件长度为0,下载失败
                return TYPE_FAILED;
            }else if(contentLength==downloadFileLength){ //下载完成
                return TYPE_SUCCESS;
            }
            //运行到这里,说明既不会这个url地址有问题,也不会说这个已经下载的文件长度已经下载完成了
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                                         .url(downloadUrl)
                                         .addHeader("RANGE","bytes="+downloadFileLength+"-")
                                         .build();
            Response response = client.newCall(request).execute();//同步堵塞
            if(response!=null){
                is = response.body().byteStream();
                savedFile = new RandomAccessFile(file, "rw");
                savedFile.seek(downloadFileLength);
                
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值