您的位置:首页 > 理论基础 > 计算机网络

Android OkHttp 文件上传和下载

2016-07-08 10:48 441 查看
相信大家对OkHttp也是相当的熟悉了,毕竟是Square的东西,对于其种种优点,这里也不再叙说。优秀是优秀,但是毕竟优秀的东西给我们封装了太多,那么问题来了,我们使用OkHttp作为我们的网络层,简单地进行GET/POST请求是毫无问题。近日看了产品的设计稿,毛估估会有文件的上传与下载的需求,如果使用OkHttp作为网络层进行封装,你会惊讶的发现,简直封装的太“完美”了。如果现在有这么一个需求,要求对文件进行上传或下载,但是在上传或者下载前,你需要给用户一个友好的提示,在上传或者下载中,你需要将进度展示给用户,下载或者完成后提示用户下载完成。

但是呢,找啊找,你会发现基本上找不到OkHttp的这种用法,百度是找不到,但是你别忘记了还有谷歌,谷歌一搜,Stackoverflow就全出来了,甚至github上的issue都出来了,可见并不是我们遇到了这么一个问题,还要许许多多的人遇到了这个问题,粗粗看了几个回答,感觉有几个还是比较靠谱的。为了日后的重用,我将其封装为一个OkHttp的扩展库,暂时取名为CoreProgress。

要实现进度的监听,需要使用到OkHttp的依赖包Okio里的两个类,一个是Source,一个是Sink,至于Okio的东西,这里也不多说。

首先我们实现文件下载的进度监听。OkHttp给我们的只是一个回调,里面有Response返回结果,我们需要继承一个类,对结果进行监听,这个类就是ResponseBody,但是如何将它设置到OkHttp中去呢,答案是拦截器。拦截器的部分后面再叙述,这里先实现ResponseBody的子类ProgressResponseBody。

要监听进度,我们必然需要一个监听器,也就是一个接口,在其实现类中完成回调内容的处理,该接口声明如下。

然后会使用到该接口

再实现我们的UI回调接口,对于文件的上传,我们需要实现的是ProgressRequestListener接口,文件的下载需要实现的是ProgressResponseListener接口,但是内部的逻辑处理是完全一样的。我们使用抽象类,提供一个抽象方法,该抽象方法用于UI层回调的处理,由具体开发去实现。涉及到消息机制就涉及到Handler类,在Handler的子类中维护一个弱引用指向外部类(用到了static防止内存泄露,但是需要调用外部类的一个非静态函数,所以将外部类引用直接由构造函数传入,在内部通过调用该引用的方法去实现),然后将主线程的Looper传入,调用父类构造函数。在onRequestProgress中发送进度更新的消息,在handleMessage函数中回调我们的抽象方法。我们只需要实现抽象方法,编写对应的UI更新代码即可。具体代码如下。

另一个实现类代码雷同,不做叙述。

最简单的一步就是在我们的程序中使用了。为了方便Android Studio用户使用,我将其发布到了中央库。加入如下依赖即可

注意OkHttp的依赖需要自己手动添加,这个库中OkHttp只是编译时依赖,并没有打包进去。

这里贴一个简单的例子,布局文件,两个进度条用于显示进度

一个上传操作,一个下载操作,分别提供了UI层与非UI层回调的示例。最终代码中使用的监听器都是UI层的,因为我们要更新进度条。

需要特别注意的一点是文件的下载中如果文件大小未知,contentLength 会始终返回-1,对于已知文件大小的情况下,它返回的是实际文件大小。但是done只要在文件下载完成后才会返回true,可以使用两者的结合进行判断文件是否下载完成。

当然,我们进行进度的监听,最终还是会回调内部的接口,如果请求成功会回调onResponse,请求失败则回调onFailure,我们可以在onResponse中处理最终的结果。比如提示用户上传完成或者下载完成等等 。

还有一个细节需要注意就是连接的超时,读取与写入数据的超时时间的设置,在读取或者写入一些大文件的时候如果不设置这个参数可能会报异常,这里就随便设置了一下值,设得有点大,实际情况按需设置。

文件的上传需要服务器的配合,为了证明PHP是世界上最好的语言,服务器的操作使用PHP大法,其实就是简单的输出POST的内容和文件的信息,并将一个文件保存到了服务器当前目录下的file文件夹下。

下面是运行结果,可以看到点击了上传或者下载后,进度条在不断更新。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: