导语
本部分内容是关于Android进阶的一些知识总结,涉及到的知识点比较杂,不过都是面试中几乎常问的知识点,也是加分的点。
关于这部分内容,可能需要有一些具体的项目实践。在面试的过程中,结合具体自身实践经历,才能更加深入透彻的描绘出来。
###目录
Android多线程断点续传
Android全局异常处理
Android MVP模式详解
Android Binder机制及AIDL使用
Android Parcelable和Serializable的区别
一个APP从启动到主页面显示经历了哪些过程?
Android性能优化总结
Android 内存泄漏总结
Android布局优化之include、merge、ViewStub的使用
Android权限处理
Android热修复原理
Android插件化入门指南
VirtualApk解析
Android推送技术解析
Android Apk安装过程
PopupWindow和Dialog区别
Android多线程断点续传
一、原理
其实断点续传的原理很简单,从字面上理解,所谓断点续传就是从停止的地方重新下载。
断点:线程停止的位置。
续传:从停止的位置重新下载。
用代码解析就是:
断点 : 当前线程已经下载完成的数据长度。
续传 : 向服务器请求上次线程停止位置之后的数据。
原理知道了,功能实现起来也简单。每当线程停止时就把已下载的数据长度写入记录文件,当重新下载时,从记录文件读取已经下载了的长度。而这个长度就是所需要的断点。
续传的实现也简单,可以通过设置网络请求参数,请求服务器从指定的位置开始读取数据。
而要实现这两个功能只需要使用到httpURLconnection里面的setRequestProperty方法便可以实现.
public void setRequestProperty(String field, String newValue)
如下所示,便是向服务器请求500-1000之间的500个byte:
conn.setRequestProperty("Range", "bytes=" + 500 + "-" + 1000);
以上只是续传的一部分需求,当我们获取到下载数据时,还需要将数据写入文件,而普通发File对象并不提供从指定位置写入数据的功能,这个时候,就需要使用到RandomAccessFile来实现从指定位置给文件写入数据的功能。
public void seek(long offset)
如下所示,便是从文件的的第100个byte后开始写入数据。
raFile.seek(100);
而开始写入数据时还需要用到RandomAccessFile里面的另外一个方法
public void write(byte[] buffer, int byteOffset, int byteCount)
该方法的使用和OutputStream的write的使用一模一样…
以上便是断点续传的原理。
二、多线程断点续传
多线程断点续传便是在单线程的断点续传上延伸的。多线程断点续传是把整个文件分割成几个部分,每个部分由一条线程执行下载,而每一条下载线程都要实现断点续传功能。
为了实现文件分割功能,我们需要使用到httpURLconnection的另外一个方法:
public int getContentLength()
当请求成功时,可以通过该方法获取到文件的总长度。
每一条线程下载大小 = fileLength / THREAD_NUM
如下图所示,描述的便是多线程的下载模型:
在多线程断点续传下载中,有一点需要特别注意:
由于文件是分成多个部分是被不同的线程的同时下载的,这就需要,每一条线程都分别需要有一个断点记录,和一个线程完成状态的记录;
只有所有线程的下载状态都处于完成状态时,才能表示文件已经下载完成。
实现记录的方法多种多样,我这里采用的是JDK自带的Properties类来记录下载参数。
三、断点续传结构
通过原理的了解,便可以很快的设计出断点续传工具类的基本结构图
IDownloadListener.java
package com.arialyy.frame.http.inf;
import java.net.HttpURLConnection;
/**
* 在这里面编写你的业务逻辑
*/
public interface IDownloadListener {
/**
* 取消下载
*/
public void onCancel();
/**
* 下载失败
*/
public void onFail();
/**
* 下载预处理,可通过HttpURLConnection获取文件长度
*/
public void onPreDownload(HttpURLConnection connection);
/**
* 下载监听
*/
public void onProgress(long currentLocation);
/**
* 单一线程的结束位置
*/
public void onChildComplete(long finishLocation);
/**
* 开始
*/
public void onStart(long startLocation);
/**
* 子程恢复下载的位置
*/
public void onChildResume(long resumeLocation);
/**
* 恢复位置
*/
public void onResume(long resumeLocation);
/**
* 停止
*/
public void onStop(long stopLocation);
/**
* 下载完成
*/
public void onComplete();
}
该类是下载监听接口
DownloadListener.java
import java.net.HttpURLConnection;
/**
* 下载监听
*/
public class D