1、 多文件下载列表的显示
2、 启动多个线程分段下载
二、 多线程下载原理简介
假设要分3个线程下载一个100字节的文件:从头到尾,每个线程下载一段
getView() 方法会重新调用一遍
1) 【问题】:多个线程在操作同一个数据库,导致数据库锁定的问题
数据库设置为单例模式,保证这个类只有一个对象,一个实例。多个实例会产生多个地方去操作数据库。单例的话,也就是说只有一个实例会对数据库进行访问操作。
2) 【单例设计】:永远只会被实例化一次
a) 私有化构造方法
b) 定义静态对象引用
c) 获得类实例的静态方法
自己创建和销毁线程也是会销毁性能的,减少线程创建和销毁所使用的时间,让程序运行速度更快。
线程组成的池塘,当线程运行完成之后,不会简单的销毁线程,而是出于等待,当有新的任务开始,就从线程池中拿出线程复用,这样就减少了线程创建和销毁的次数,提高了程序运行的性能。
1) 线程池接口:ExecutorService
提供对线程池中的线程进行集中的管理,比如在某一段时间内,启动某些任务,可以对所有的线程进行停止,启动的任务。减少线程创建和销毁所使用的时间,便于服务器进行管理。减少了服务器频繁创建线程的资源消耗。
2) Executors类提供四种线程池:
a) newCachedThreadPool():带缓存的线程池
线程池中的线程个数对于任务所需要的线程个数,就会将空闲的线程回收
一旦线程中的线程不足任务所需的线程,就会将回收的线程重新拿取出来进行使用。
线程数量大小没有进行限制,与能够系统支持的线程数量有关
b) newFixedThreadPool(int):固定线程数量的线程池
c) newScheduledThreadPool():可以周期性的,定时的去执行任务,线程数量没有做限制
d) newSingleThreadExecutor():单个线程的线程池
所有的任务排队执行,先来先执行
1) 分段下载:一个文件分成了的多段进行下载,每一个线程下载文件中的某个范围
a) 下载之前需要先计算出每个线程需要下载的长度,根据文件的长度/开启线程的个数
b) 开启线程下载,通过Range 设置开始下载点和结束下载点,来获取每个线程要下载的数据范围
conn.setRequestProperty("Range", "bytes=" + start + "-" + end);
2) 线程池:对线程进行管理,会减少线程开销。
线程池采用的是newCachedThreadPool带缓存的线程池,excute执行线程。好处是,减少了线程创建和销毁所需要的时间,线程池会直接将空闲的线程拿过来进行使用。
把线程下载的进度保存起来,保存到数据库中。
多线程对数据库的访问可能会造成数据库的表或者数据库的锁定。
1) 单例模式:
通过数据库的帮助类DBHelper来操作数据库,如果有多个实例的话,就会在多个地方操作数据库,这是不安全的,所以将DBHelper设计为单例模式。
a) 将构造方法私有化
b) 初始化静态对象引用
c) 创建静态公共方法getIntance,保证该数据库帮助类DBHelper只创建一次
先判断静态对象是否为空
如果为空,创建该数据库帮助类DBHelper
返回该数据库帮助类DBHelper
2) 线程安全:
a) 将数据库的增删改都设置为synchronized同步方法,保证同一时间段只有一个线程在操作修改数据库内容
b) 查询数据库不需要设置synchronized同步方法,因为并没有对数据库进行操作。使用同步方法会销毁程序运行的性能,所以查询建议不用使用同步锁。
c) 修改获取查询数据库的方式:
获取可读数据库:(查询)
SQLiteDatabase database = dbHelper.getReadableDatabase();
获取可写数据库:(增删改)
SQLiteDatabase database = dbHelper.getWritableDatabase();
1) 网络连接:通过HttpURLConnection设置和获取网络请求
2) 文件操作:关键使用RandomAccessFile文件操作流,可以在文件的任意位置开始写入,通过使用seek(index)设置文件写入的指针位置
1) 【问题】当一个屏幕不能显示全部的item的时候,就会因为item的复用而出现错乱
2) 【原因】设置文件名和按钮的操作放在第一次实例化的括号里是不可取的。
生成list的 mFileList的时候 注意添加的fileinfo的 id要和position一致,不然会错乱(这点不太好 比如加入删除任务功能后会比较麻烦)
3、 下载,停止按钮注意不能多次点击需要可以在代码中进行限制 4、 退出Activity时,线程仍然会下载一段时间且不会保存可以在service的onDestory() 方法中对map mtasks遍历 改isPaused为true
5、 删除未完成下载文件后,数据库中未删除,会导致下载不完整可以在service中初始化时判断文件是否存在
6、 ftruncate failed:ENOSPC(No space left on device)1) 【报错地方】accessFile.setLength(length);
2) 【原因】是需要下载的内容超过了Android设备的可存储空间。
1) 【问题】设置进度的时候,由于下载内容过大,mFinished 100 会导致丢失精度
2) 【解决】intent.putExtra("finished", (int) (mFinished 1.0 / mFileInfo.getLength() * 100)); 并且可以使用long类型
代码后续导入