这个项目是什么
RetrofitDownloadManager 解决的是 App 里"多个文件同时下载、中途断了能接着下、进度要实时显示在列表里"这件事。README 给出的技术组合是 RxJava + Retrofit + SqlBrite + SqlDelight,作者另有一篇文章专门讲源码,链接放在仓库里。
断点续传本身不算难,难的是把下载状态持久化,再把状态变化推回界面。这个项目的做法是用数据库存任务和进度,用响应式的方式把数据库变化变成列表更新,整体思路值得参考。
技术组合的分工
- Retrofit 负责网络请求,下载任务最终都落到它身上;
- RxJava 串起下载流程和线程切换,也是回调和进度传递的基础;
- SqlDelight 用 SQL 生成类型安全的 Java 接口,省掉手写 DAO 的重复劳动;
- SqlBrite 把 SQLite 查询包成可观察对象,数据一变,订阅方就能收到通知。
这四个库各管一段:网络、异步、持久化、状态推送,拼起来正好覆盖一个下载管理器的完整职责。
使用方法
以 module 形式添加到项目。
在 Application 里初始化下载器:
DownManager.init(this);
- 添加下载任务,参数依次是文件保存路径、完整的下载 URL、任务名称:
//创建基本任务,参数为:文件保存的路径、下载的url要全路径、下载任务的名称
DownInfo downInfo = DownInfo.builder().create(getPath(url), url, name);
//开始下载
DownManager.getInstance().startDown(downInfo);
- 查询当前的下载列表:
//查询当前所有的下载
DBUtil.getInstance().getAllDown()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(adapter);
- 设置 View 的回调监听器。README 特别提醒要设置两个:一个在 ViewHolder 初始化时通过 RxBus 挂上,另一个在
onBindViewHolder时添加。
public ListViewHolder(View itemView) {
super(itemView);
// 初始化View
mBtHandle.setOnClickListener(this);
//因为(downInfo.downUrl()用来传递进度信息,这里使用两个(downInfo.downUrl()进行标识
RxBus.with().setEvent(DownManager.DOWN_ADD_SUBSCRIBE)
.onNext(new Action1<Events<?>>() {
@Override
public void call(Events<?> events) {
//添加监听器,在列表点击开始回调
String link = events.getContent();
link = link.replace(DownManager.DOWN_ADD_SUBSCRIBE, "");
DownManager.getInstance().addListener(link, listener);
}
}).create();
}
@Override
public void onBindViewHolder(final ListViewHolder holder, final int position) {
//在Holder里面设置数据
//添加View监听器
DownManager.getInstance().addListener(downInfo.downUrl(), listener);
}
踩坑与思考
README 强调"要设置两个 View 的回调监听器",这是使用这套代码时最容易漏的地方。一个可能的原因是列表复用:同一个 item 在不同位置会绑定不同的下载任务,只在初始化时挂一次监听,滚动之后进度就会串到别的行上。所以绑定数据时要重新 addListener。
另外,进度是按 downInfo.downUrl() 来对应任务的,README 的注释里写得很直白。用 URL 作为标识,意味着同一个地址在管理器里只对应一份任务状态;如果你的场景需要同一个文件发起多个独立任务,这一点要提前考虑。
最后,这套代码基于 RxJava 1 时代的 Action1、Events 等类型,直接搬到新项目里需要先做一轮升级。