Android 断点续传进阶之多线程下载

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

完整开源地址:https://docs.qq.com/doc/DSkNLaERkbnFoS0ZF

for (TheardInfo info : threaddInfos) {

DownloadThread thread = new DownloadThread(info);

// thread.start(); //开始线程添加到集合中

DuoDownloadTask.executorService.execute(thread); //利用线程池来执行线程任务

downloadThreadList.add(thread); //把线程添加进去方便ckeckAllThreadFinshed检查线程

}

}

//这个方法 用来判断所有的线程是否都执行完了

private synchronized void checkAllThreadFinshed() {

boolean allFinished = true;

//遍历线程集合,判断线程是否都执行完毕

for (DownloadThread thread : downloadThreadList) {

if (!thread.isFinished) {

allFinished = false;

break;

}

}

if (allFinished) { //如果线程都完成了

//下载完成后 删除线程信息

//删除下载记录

mThreadDAO.deleteThread(mFileInfo.getUrl(), mFileInfo.getId());

//发送广播通知ui下载任务结束

Intent intent = new Intent(DuoDownloadService.ACTION_FINISHED);

intent.putExtra(“fileInfo”, mFileInfo);

mContext.sendBroadcast(intent); //发送广播

}

}

class DownloadThread extends Thread {

private TheardInfo threadInfo;

public boolean isFinished = false; //用来标识线程是否结束

public DownloadThread(TheardInfo threadInfo) {

this.threadInfo = threadInfo;

}

@Override

public void run() {

//设置下载位置

try {

URL url = new URL(threadInfo.getUrl());

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod(“GET”);

conn.setConnectTimeout(3000);

//开始的字节数 为开始加上完成的长度

long start = threadInfo.getStart() + threadInfo.getFinished();

//下载的范围 开始的字节数 到结束的字节数

conn.setRequestProperty(“Range”, “bytes=” + start + “-” + threadInfo.getEnd());

//设置文件写入位置 路径 文件名

File file = new File(DownloadService.DOWNLOAD_PATH, mFileInfo.getFileName());

//

RandomAccessFile raf = new RandomAccessFile(file, “rwd”);

raf.seek(start); //文件的写入位置

Intent intent = new Intent(DownloadService.ACTION_UPDATE);//把进度广播发送给activity 所以需要intent

mFinished += threadInfo.getFinished();//从线程中拿到完成的进度

//开始下载

if (conn.getResponseCode() == 206) {

//读取数据

InputStream input = conn.getInputStream();

byte[] buffer = new byte[1024 * 4];

int len = -1;

long time = System.currentTimeMillis(); //拿到当前时间

while ((len = input.read(buffer)) != -1) {

//写入文件

raf.write(buffer, 0, len);

//把下载进度发送广播给activity

mFinished += len; //把现在下载的进度累加进去

//累加每个线程完成的进度

threadInfo.setFinished(threadInfo.getFinished() + len);

if (System.currentTimeMillis() - time > 1000) { //减少ni负载 大于10秒发送更新

time = System.currentTimeMillis();

//以百分比的形式发送给广播

intent.putExtra(“finished”, (int) (mFinished * 100 / mFileInfo.getLength()));

intent.putExtra(“id”, mFileInfo.getId());

mContext.sendBroadcast(intent);

}

//在下载暂停时,保存下载进度

if (isPause) { //如果暂停 把线程信息进行保存 最后一个参数 他会把每个线程的 进度保存起来

mThreadDAO.updateThread(mFileInfo.getUrl(), mFileInfo.getId(), threadInfo.getFinished());

return;

}

}

intent.putExtra(“finished”, 100);

mContext.sendBroadcast(intent); //发送广播

// 标识线程执行完毕

isFinished = true;

//每个线程执行完毕 都执行去判断 所有的线程是否都执行完毕

checkAllThreadFinshed();

input.close();

}

raf.close();

conn.disconnect();

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally { //关闭各种链接

}

super.run();

}

}

}

ThreadDAOImpl.java

/**

  • 数据访问接口实现类

  • Created by lung on 2016-12-07.

*/

public class ThreadDAOImpl implements ThreadDAO {

private DBHelper mHelper=null;

public ThreadDAOImpl(Context context){

mHelper=DBHelper.getInstance(context);

}

//插入线程信息

@Override

public synchronized void insertThread(TheardInfo threadInfo) { //加锁进行同步

SQLiteDatabase db=mHelper.getWritableDatabase();//获得可写的数据库

db.execSQL(“insert into thread_info(thread_id,url,start,end,finished) values(?,?,?,?,?)”,new Object[]{threadInfo.getId(), threadInfo.getUrl(),

threadInfo.getStart(), threadInfo.getEnd(), threadInfo.getFinished()});

db.close();

}

//删除线程

@Override

public synchronized void deleteThread(String url, int thread_id) {

SQLiteDatabase db=mHelper.getWritableDatabase();//获得可写的数据库

db.execSQL(“delete from thread_info where url = ? and thread_id=?”,

new Object[]{url, thread_id});

db.close();

}

//更新线程下载进度

@Override

public synchronized void updateThread(String url, int thread_id, long finished) {

SQLiteDatabase db=mHelper.getWritableDatabase();//获得可写的数据库

db.execSQL(“update thread_info set finished = ? where url = ? and thread_id=?”,

new Object[]{finished, url, thread_id});

db.close();

}

//查询文件的线程信息

@Override

public List getThreads(String url) {

List list = new ArrayList<>();

SQLiteDatabase db = mHelper.getWritableDatabase();

Cursor cursor = db.rawQuery(“select * from thread_info where url=?”, new String[]{url});

while (cursor.moveToNext()) {

TheardInfo thread = new TheardInfo();

thread.setId(cursor.getInt(cursor.getColumnIndex(“thread_id”)));

thread.setUrl(cursor.getString(cursor.getColumnIndex(“url”)));

thread.setStart(cursor.getInt(cursor.getColumnIndex(“start”)));

thread.setEnd(cursor.getInt(cursor.getColumnIndex(“end”)));

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值