凯发真人娱乐

android 多线程下载 断点续传 -凯发真人娱乐

2023-08-12,,

来源:网易云课堂android极客班第八次作业练习

练习内容: asynctask handler

多线程下载的原理

首先获取到目标文件的大小,然后在磁盘上申请一块空间用于保存目标文件,接着把目标文件分割成n份,分别创建线程下载.

获取目标文件的大小

                    //使用目标文件的下载链接作为发起网络请求
murl = new ;
//注意不是urlconnection, urlconnection是抽象类,httpurlconnection是它的子类
httpurlconnection urlconnection = (httpurlconnection) murl.openconnection();
urlconnection.setrequestmethod("get");
urlconnection.setconnecttimeout(5000); //获取目标文件的大小
mcontentlength = urlconnection.getcontentlength();

在磁盘上申请一块空间,用于保存目标文件,这里用到了randomaccessfile类,该类的seek()方法能够非常方便的对文件进行指定位置的定位.

                    mfile = new file(environment.getexternalstoragedirectory(), getfilename(params[0]));
if (mfile.exists()) {//如果文件已经存在,删除
mfile.delete();
}
randomaccessfile randomfile = new randomaccessfile(mfile, "rw");
//设置文件大小
randomfile.setlength(mcontentlength);

分割文件,分别创建线程进行下载(只需要关注非注释内容)

                    int blocksize = mcontentlength / 3;
for (int i = 0; i < 3; i ) {
int begin = i * blocksize;
int end = (i 1) * blocksize - 1;
if (i == 2) {
end = mcontentlength;
}
//hashmap map = new hashmap<>();
//map.put("begin", begin);
//map.put("end", end);
//map.put("finished", 0);
//threadlist.add(map); //new thread
new thread(new downloadthread(i, begin, end, mfile, murl)).start();
}

的原理

在每个线程进行下载的过程中,每次写入文件的时候,记录已经下载了多少内容,重新开始下载时,从上次结束的位置继续下载.

数据结构

使用hashmap存储该线程下载文件的起始位置,结束位置和已完成大小,并使用一个arraylist存储各线程数据

    private list> threadlist = new arraylist<>();
                        hashmap map = new hashmap<>();
map.put("begin", begin);//开始位置
map.put("end", end);//结束位置
map.put("finished", 0);//已完成

发起网络请求时,指定起止位置

                httpurlconnection urlconnection = (httpurlconnection) url.openconnection();
urlconnection.setrequestmethod("get"); //指定起止位置
urlconnection.setrequestproperty("range", "bytes=" begin "-" end);

下载时更新map中的finished字段的值

                while ((len = is.read(buf)) != -1 && isdownloading) {
randomfile.write(buf, 0, len);
updateprogress(len); //更新map中的finished字段的值
map.put("finished", map.get("finished") len);
}

再次开始下载时,更新每个线程的开始位置(即实例化downloadthread类时所需要的第二个参数)

                for (int i = 0; i < threadlist.size(); i  ) {
hashmap map = threadlist.get(i);
new thread(new downloadthread(i, map.get("begin") map.get("finished"), map.get("end"), mfile, murl)).start();
}

更新ui的操作

自定义handler

            public static class downloadhandler extends android.os.handler {
public final weakreference mactivity; public downloadhandler(mainactivity activity) {
mactivity = new weakreference(activity);
} @override
public void handlemessage(message msg) {
super.handlemessage(msg);
mainactivity activity = mactivity.get(); switch (msg.what) {
case 0:
int progress = (int) msg.obj;
activity.getprogressbar().setprogress(progress);
if (progress == 100) {
// toast.maketext(activity, "下载成功",toast.length_short).show();
activity.getdownloadbutton().settext("下载成功");
}
}
}
}

更新ui的方法

            //使用synchronized
synchronized private void updateprogress(int len) {
total = len;
int temp = total * 100 / mcontentlength;
mdownloadhandler.obtainmessage(0, temp).sendtotarget();
}

完整代码github地址:https://github.com/zhangbz/multithreadingdownloaddemo

android 多线程下载 断点续传的相关教程结束。

网站地图