首先先感谢丰神,本文源于他的这篇微博http://blog.csdn.net/cfy137000/article/details/54838608,思路很棒,然后自己跟着代码撸了一遍,然后为了加深理解就上传到博客上来。
首先说下主要都到了什么开发技术吧,网络请求是使用okhttp,然后涉及多线程的部分是使用rxjava,之前自己只是简单的看了一下rxjava,然后实际运用了下,感觉熟悉了很多;然后还涉及到了lambda表达式以及文件的流的读写,开发要求的jdk的版本的要求是在1.8以上,不然没办法支持lambda表达式。
首先是配置gradle,导入okhttp以及rxjava,//OKHttp
compile 'com.squareup.okhttp3:okhttp:3.6.0'
//RxJava和RxAndroid 用来做线程切换的
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
然后,//开启Java1.8 能够使用lambda表达式
compileOptions{
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
//为了开启Java8
jackOptions{
enabled true;
}
然后大概思路捋了下:
1,使用单例模式初始化okhttpclient,同时使用hashmap来存放请求;
2.使用rxjava进行下载的一些操作;
3.点击暂停的时候,通过hashmap移除请求;
4.断点续传主要是包括:移除请求,判断本地是否有下载的文件,比较本地文件和下载文件的大小,重新开始请求;
5.需要提到的一点是我们通过添加请求头来实现接着之前的进度继续下载。
为了开发方便新建了一个包括下载信息的实体类(downloadInfo),一个数据接受(downloadObserver),
还有一个关闭流的工具类(IOUtil),新建了一个application(myApp).
1.跟着思路开始理解代码,首先来说的是单例模式的实现,这里涉及到了一个之前没有接触的新东西(AtomicReference),百度了一下,介绍说这是java的原子性引用,在多线程的情况下更新对象可以保持一致性;然后这里用来实现单例
//获得一个单例类
public static DownloadManager getInstance() {
for (; ; ) {
DownloadManager current = INSTANCE.get();
if (current != null) {
return current;
}
current = new DownloadManager();
if (INSTANCE.compareAndSet(null, current)) {
return current;
}
}
}
private DownloadManager() {
downCalls = new HashMap<>();
mClient = new OkHttpClient.Builder().build();
}
其中的comareAndSet方法的意思是如果此方法的调用者和参数一相等,那么就将参数二的值赋值给调用者;然后构造方法私有化。
2.
然后就是下载文件的方法,先看代码:
/**
* 开始下载
*
* @param url