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

练习内容: 多线程 asyncTask handler

多线程下载的原理

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

获取目标文件的大小

  1. //使用目标文件的下载链接作为发起网络请求
  2. mUrl = new URL("http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk");
  3. //注意不是URLConnection, URLConnection是抽象类,HttpURLConnection是它的子类
  4. HttpURLConnection urlConnection = (HttpURLConnection) mUrl.openConnection();
  5. urlConnection.setRequestMethod("GET");
  6. urlConnection.setConnectTimeout(5000);
  7. //获取目标文件的大小
  8. mContentLength = urlConnection.getContentLength();

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

  1. mFile = new File(Environment.getExternalStorageDirectory(), getFileName(params[0]));
  2. if (mFile.exists()) {//如果文件已经存在,删除
  3. mFile.delete();
  4. }
  5. RandomAccessFile randomFile = new RandomAccessFile(mFile, "rw");
  6. //设置文件大小
  7. randomFile.setLength(mContentLength);

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

  1. int blockSize = mContentLength / 3;
  2. for (int i = 0; i < 3; i++) {
  3. int begin = i * blockSize;
  4. int end = (i + 1) * blockSize - 1;
  5. if (i == 2) {
  6. end = mContentLength;
  7. }
  8. //HashMap<String, Integer> map = new HashMap<>();
  9. //map.put("begin", begin);
  10. //map.put("end", end);
  11. //map.put("finished", 0);
  12. //threadList.add(map);
  13. //new Thread
  14. new Thread(new DownloadThread(i, begin, end, mFile, mUrl)).start();
  15. }

断点续传的原理

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

数据结构

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

  1. private List<HashMap<String, Integer>> threadList = new ArrayList<>();
  1. HashMap<String, Integer> map = new HashMap<>();
  2. map.put("begin", begin);//开始位置
  3. map.put("end", end);//结束位置
  4. map.put("finished", 0);//已完成

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

  1. HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
  2. urlConnection.setRequestMethod("GET");
  3. //指定起止位置
  4. urlConnection.setRequestProperty("Range", "bytes=" + begin + "-" + end);

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

  1. while ((len = is.read(buf)) != -1 && isDownloading) {
  2. randomFile.write(buf, 0, len);
  3. updateProgress(len);
  4. //更新map中的finished字段的值
  5. map.put("finished", map.get("finished") + len);
  6. }

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

  1. for (int i = 0; i < threadList.size(); i++) {
  2. HashMap<String, Integer> map = threadList.get(i);
  3. new Thread(new DownloadThread(i, map.get("begin") + map.get("finished"), map.get("end"), mFile, mUrl)).start();
  4. }

更新ui的操作

自定义handler

  1. public static class DownloadHandler extends android.os.Handler {
  2. public final WeakReference<MainActivity> mActivity;
  3. public DownloadHandler(MainActivity activity) {
  4. mActivity = new WeakReference<MainActivity>(activity);
  5. }
  6. @Override
  7. public void handleMessage(Message msg) {
  8. super.handleMessage(msg);
  9. MainActivity activity = mActivity.get();
  10. switch (msg.what) {
  11. case 0:
  12. int progress = (int) msg.obj;
  13. activity.getProgressBar().setProgress(progress);
  14. if (progress == 100) {
  15. // Toast.makeText(activity, "下载成功",Toast.LENGTH_SHORT).show();
  16. activity.getDownloadButton().setText("下载成功");
  17. }
  18. }
  19. }
  20. }

更新UI的方法

  1. //使用synchronized
  2. synchronized private void updateProgress(int len) {
  3. total += len;
  4. int temp = total * 100 / mContentLength;
  5. mDownloadHandler.obtainMessage(0, temp).sendToTarget();
  6. }

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

android 多线程下载 断点续传的更多相关文章

  1. android程序---->android多线程下载(一)

    多线程下载是加快下载速度的一种方式,通过开启多个线程去执行一个任务,可以使任务的执行速度变快.多线程的任务下载时常都会使用得到断点续传下载,就是我们在一次下载未结束时退出下载,第二次下载时会接着第一次 ...

  2. android程序---->android多线程下载(二)

    上篇我们讲到了android中下载的断点续传问题,今天我们开始学习下载的多线程问题.本次的多线程源码下载:androdi中多线程下载的实现代码.有关断点续传的问题,请参见博客:android程序--- ...

  3. Andoid 更好的Android多线程下载框架

    概述 为什么是更好的Android多线程下载框架呢,原因你懂的,广告法嘛! 本篇我们我们就来聊聊多线程下载框架,先聊聊我们框架的特点: 多线程 多任务 断点续传 支持大文件 可以自定义下载数据库 高度 ...

  4. 更好的Android多线程下载框架

    /** * 作者:Pich * 原文链接:http://me.woblog.cn/ * QQ群:129961195 * Github:https://github.com/lifengsofts */ ...

  5. 无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)

    1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...

  6. Android 多线程下载,断点续传,线程池

    你可以在这里看到这个demo的源码: https://github.com/onlynight/MultiThreadDownloader 效果图 这张效果图是同时开启三个下载任务,限制下载线程数量的 ...

  7. Java--使用多线程下载,断点续传技术原理(RandomAccessFile)

    一.基础知识 1.什么是线程?什么是进程?它们之间的关系? 可以参考之前的一篇文章:java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器 简 ...

  8. *Android 多线程下载 仿下载助手

    今天带来一个多线程下载的 样例.先看一下效果.点击 下载 開始下载,同一时候显示下载进度.完成下载,变成程 安装,点击安装 提示 安装应用. 界面效果 线程池 ThreadPoolExecutor , ...

  9. Android多线程下载大文件解析

    1.多线程介绍 用过迅雷的同学都知道.迅雷有个功能叫做多线程.另一个叫离线下载,我们这里重点介绍一下多线程下载.多线程,顾名思义就是非常多歌线程同一时候在执行,为什么要提出多线程这个概念呢?由于有时候 ...

随机推荐

  1. 我的游戏蜗牛web前端面试经历

    蜗牛在江苏苏州地区应该算是比较大的互联网公司了,可以称得上中国游戏的鼻祖,之前一直很想进蜗牛,但作为一个应届毕业生却没有看到蜗牛发布任何关于招聘实习生的职位,无奈之下于是就毛遂自荐了,主动以邮件的形式 ...

  2. C语言学习020:可变参数函数

    顾名思义,可变参数函数就是参数数量可变的函数,即函数的参数数量是不确定的,比如方法getnumbertotal()我们即可以传递一个参数,也可以传递5个.6个参数 #include <stdio ...

  3. 简单横道图Demo

    代码(每个月都显示整月): @{ ViewBag.Title = "横道图"; Layout = "~/Views/Shared/_Layout.cshtml" ...

  4. List<T>保存为XML文件

    今天我们学习怎样把List<T>写成一个XML文件保存起来.因为我们在做动态网站开发时,需要对一些不太常变化的数据产生为XML文件,让程序直接去读取,而不是每次是SQL数据库取. 为了解决 ...

  5. Sqlserver2005日志文件太大,使其减小的方法

    Sqlserver2005日志文件太大,使其减小的方法: 运行下面的三行 dbName为数据库名: backup log dbNamewith NO_LOG backup log dbNamewith ...

  6. iOS阶段学习第三天笔记(运算符)

    iOS学习(C语言)知识点整理笔记 1.运算符 一.算术运算符 1)表达式由变量.常量.运算符构成,有确定的类型和值 2)算术运算符包括: +(加),-(减),*(乘),/(除),%(模) 3)算术运 ...

  7. Android使用SAX解析XML(2)

    school类包含了一个major列表,可以增加该列表的元素,以及返回该列表,还实现了Parcelable.Creator接口. package com.hzhi.my_sax; import jav ...

  8. CRC编码

    一.循环冗余码校验英文名称为Cyclical Redundancy Check,简称CRC. 它是利用除法及余数的原理来作错误侦测(Error Detecting)的.实际应用时,发送装置计算出CRC ...

  9. 点我吧工作总结(技术篇) Cobar原理和环境搭建

    我思故我在,提问启迪思考! 1.什么是Cobar? Cobar是关系型数据的分布式处理系统,它可以在分布式的环境下看上去像传统数据库一样为您提供海量数据服务.cobar已经在阿里巴巴B2B公司稳定运行 ...

  10. Java关于Properties用法的总结(一)

    最近项目中有一个这样的需求,要做一个定时任务功能,定时备份数据库的操表,将表数据写入txt文件.因为文件的读写路径可能需要随时改动,所以写死或者写成静态变量都不方便,就考虑使用配置文件,这里总结些配置 ...