什么都先别说,先看预览图!
预览图中是限制了同时最大下载数为 2 的.
其实下载管理器的实现是挺简单的,我们需要弄清楚几点就行了
1.所有任务的Bean应该存在哪里,用什么存?
2.如何判断任务是否已存在?
3.如何判断任务是新的任务或是从等待中恢复的任务?
4.应该如何把下载列表传递给Adapter?
5.如何将下载的进度传递出去?
6.如何有效率地刷新显示的列表? (ListView 或 RecycleView)
服务基础
首先我们需要明确一点,下载我们应该使用服务来进行,这样我们才能进行后台下载。
所以我们就开始创建我们的Service:
public class OCDownloadService extends Service{
... ...
@Nullable
@Override
public IBinder onBind(Intent intent) {
//当服务被Bind的时候我们就返回一个带有服务对象的类给Bind服务的Activity
return new GetServiceClass();
}
/**
* 传递服务对象的类
*/
public class GetServiceClass extends Binder{
public OCDownloadService getService(){
return OCDownloadService.this;
}
}
... ...
}
然后我们在AndroidManifest.xml里面注册一下:
<service android:name=".OCDownloader.OCDownloadService"/>
下载请求的检查与处理
然后我们就开始进入正题 !
首先第一点,我们使用HashMap来当作储存下载任务信息的总表,这样的好处是我们可以在查找任务的时候通过 Key 来查询,而不需要通过遍历 List 的方法来获取任务信息。而且我们传递的时候可以直接使用它的一份Copy就行了,不需要把自己传出去。
下面我们来看代码:
(关于Service的生命周期啥的我就不再重复说了。我这里使用的是本地广播来传输下载信息的更新。剩下的在代码注释中有详细的解释)
public class OCDownloadService extends Service{
static final int MAX_DOWNLOADING_TASK = 2; //最大同时下载数
private LocalBroadcastManager broadcastManager;
private HashMap<String,DLBean> allTaskList;
private OCThreadExecutor threadExecutor;
private boolean keepAlive = false;
private int runningThread = 0;
@Override
public void onCreate() {
super.onCreate();
//创建任务线程池
if (threadExecutor == null){
threadExecutor = new OCThreadExecutor(MAX_DOWNLOADING_TASK,"downloading");
}
//创建总表对象
if (allTaskList == null){
allTaskList = new HashMap<>();
}
//创建本地广播器
if (broadcastManager == null){
broadcastManager = LocalBroadcastManager.getInstance(this);
}
}
/**
* 下载的请求就是从这里传进来的,我们在这里进行下载任务的前期处理
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//检测传过来的请求是否完整。我们只需要 下载网址、文件名、下载路径 即可。
if (intent != null && intent.getAction() != null && intent.getAction().equals("NewTask")){
String url = intent.getExtras().getString("url");
String title = intent.getExtras().getString("title");
String path = intent.getExtras().getString("path");
//检测得到的数据是否有效
if (TextUtils.isEmpty(url) || TextUtils.isEmpty(title) || TextUtils.isEmpty(path)){
Toast.makeText(OCDownloadService.this,"Invail data",Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent, flags, startId);
}else {
//如果有效则执行检查步骤
checkTask(new DLBean(title,url,path));
}
}
return super.onStartCommand(intent, flags, startId);
}
/**
* 检查新的下载任务
* @param requestBean 下载对象的信息Bean
*/
private synchronized void checkTask(@Nullable DLBean requestBean){
if (requestBean != null){
//先检查是否存在同名的文件
if (new File(requestBean.getPath()+"/"+requestBean.getTitle()).exists()){
Toast.