Skip to content

Commit d43fa5a

Browse files
committed
update
1 parent a7bbf66 commit d43fa5a

12 files changed

+146
-116
lines changed

BasicKnowledge/多线程断点下载.md

+92-68
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,39 @@
1313
private static final String DIR_PATH = "F:/Download"; // 下载目录
1414

1515
public MultiThreadDownloader(String address) throws IOException {
16-
url = new URL(address); // 记住下载地址
17-
file = new File(DIR_PATH, address.substring(address.lastIndexOf("/") + 1)); // 截取地址中的文件名, 创建本地文件
18-
// 创建一个临时文件路径
16+
// 记住下载地址
17+
url = new URL(address);
18+
// 截取地址中的文件名, 创建本地文件
19+
file = new File(DIR_PATH, address.substring(address.lastIndexOf("/") + 1));
1920
}
2021

2122
public void download() throws IOException {
2223
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
2324
conn.setConnectTimeout(3000);
2425

25-
long totalLen = conn.getContentLength(); // 获取文件总长度
26-
threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT; // 计算每个线程要下载的长度
27-
26+
// 获取文件总长度
27+
long totalLen = conn.getContentLength();
28+
// 计算每个线程要下载的长度
2829
// 总长度 如果能整除 线程数, 每条线程下载的长度就是 总长度 / 线程数
2930
// 总长度 如果不能整除 线程数, 那么每条线程下载长度就是 总长度 / 线程数 + 1
31+
threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT;
3032

31-
RandomAccessFile raf = new RandomAccessFile(file, "rw"); // 在本地创建一个和服务端大小相同的文件
32-
raf.setLength(totalLen); // 设置文件的大小, 写入了若干个0
33+
// 在本地创建一个和服务端大小相同的文件
34+
RandomAccessFile raf = new RandomAccessFile(file, "rw");
35+
// 设置文件的大小, 写入了若干个0
36+
raf.setLength(totalLen);
3337
raf.close();
3438

35-
// 创建临时文件
36-
37-
for (int i = 0; i < THREAD_AMOUNT; i++) // 按照线程数循环
38-
new DownloadThread(i).start(); // 开启线程, 每个线程将会下载一部分数据到本地文件中
39+
// 按照线程数循环
40+
for (int i = 0; i < THREAD_AMOUNT; i++) {
41+
// 开启线程, 每个线程将会下载一部分数据到本地文件中
42+
new DownloadThread(i).start();
43+
}
3944
}
4045

4146
private class DownloadThread extends Thread {
42-
private int id; // 用来标记当前线程是下载任务中的第几个线程
47+
// 用来标记当前线程是下载任务中的第几个线程
48+
private int id;
4349

4450
public DownloadThread(int id) {
4551
this.id = id;
@@ -48,24 +54,28 @@
4854
public void run() {
4955
// 从临时文件读取当前线程已完成的进度
5056

51-
long start = id * threadLen; // 起始位置
52-
long end = id * threadLen + threadLen - 1; // 结束位置
57+
long start = id * threadLen;
58+
long end = id * threadLen + threadLen - 1;
5359
System.out.println("线程" + id + ": " + start + "-" + end);
5460

5561
try {
5662
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
5763
conn.setConnectTimeout(3000);
58-
conn.setRequestProperty("Range", "bytes=" + start + "-" + end); // 设置当前线程下载的范围(start和end都包含)
64+
// 设置当前线程下载的范围(start和end都包含)
65+
conn.setRequestProperty("Range", "bytes=" + start + "-" + end);
5966

60-
InputStream in = conn.getInputStream(); // 获取连接的输入流, 用来读取服务端数据
61-
RandomAccessFile raf = new RandomAccessFile(file, "rw"); // 随机读写文件, 用来向本地文件写出
62-
raf.seek(start); // 设置保存数据的位置
67+
InputStream in = conn.getInputStream();
68+
// 随机读写文件, 用来向本地文件写出
69+
RandomAccessFile raf = new RandomAccessFile(file, "rw");
70+
// 设置保存数据的位置
71+
raf.seek(start);
6372

64-
byte[] buffer = new byte[1024 * 100]; // 每次拷贝100KB
73+
// 每次拷贝100KB
74+
byte[] buffer = new byte[1024 * 100];
6575
int len;
6676
while ((len = in.read(buffer)) != -1) {
67-
raf.write(buffer, 0, len); // 从服务端读取数据, 写到本地文件
68-
// 存储当前下载进度到临时文件
77+
// 从服务端读取数据, 写到本地文件
78+
raf.write(buffer, 0, len);
6979
}
7080
raf.close();
7181

@@ -85,95 +95,109 @@
8595
2. 断点下载
8696
```java
8797
public class BreakpointDownloader {
88-
private static final String DIR_PATH = "F:/Download"; // 下载目录
89-
private static final int THREAD_AMOUNT = 3; // 总线程数
90-
91-
private URL url; // 目标下载地址
92-
private File dataFile; // 本地文件
93-
private File tempFile; // 用来存储每个线程下载的进度的临时文件
94-
private long threadLen; // 每个线程要下载的长度
95-
private long totalFinish; // 总共完成了多少
96-
private long totalLen; // 服务端文件总长度
97-
private long begin; // 用来记录开始下载时的时间
98+
// 下载目录
99+
private static final String DIR_PATH = "F:/Download";
100+
// 总线程数
101+
private static final int THREAD_AMOUNT = 3;
102+
103+
// 目标下载地址
104+
private URL url;
105+
// 本地文件
106+
private File dataFile;
107+
// 用来存储每个线程下载的进度的临时文件
108+
private File tempFile;
109+
// 每个线程要下载的长度
110+
private long threadLen;
111+
// 总共完成了多少
112+
private long totalFinish;
113+
// 服务端文件总长度
114+
private long totalLen;
115+
// 用来记录开始下载时的时间
116+
private long begin;
98117

99118
public BreakpointDownloader(String address) throws IOException {
100-
url = new URL(address); // 记住下载地址
101-
dataFile = new File(DIR_PATH, address.substring(address.lastIndexOf("/") + 1)); // 截取地址中的文件名, 创建本地文件
102-
tempFile = new File(dataFile.getAbsolutePath() + ".temp"); // 在本地文件所在文件夹中创建临时文件
119+
url = new URL(address);
120+
dataFile = new File(DIR_PATH, address.substring(address.lastIndexOf("/") + 1));
121+
tempFile = new File(dataFile.getAbsolutePath() + ".temp");
103122
}
104123

105124
public void download() throws IOException {
106125
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
107126
conn.setConnectTimeout(3000);
108127

109-
totalLen = conn.getContentLength(); // 获取服务端发送过来的文件长度
110-
threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT; // 计算每个线程要下载的长度
128+
totalLen = conn.getContentLength();
129+
threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT;
111130

112-
if (!dataFile.exists()) { // 如果本地文件不存在
113-
RandomAccessFile raf = new RandomAccessFile(dataFile, "rws"); // 在本地创建文件
114-
raf.setLength(totalLen); // 设置文件的大小和服务端相同
131+
if (!dataFile.exists()) {
132+
RandomAccessFile raf = new RandomAccessFile(dataFile, "rws");
133+
raf.setLength(totalLen);
115134
raf.close();
116135
}
117136

118-
if (!tempFile.exists()) { // 如果临时文件不存在
119-
RandomAccessFile raf = new RandomAccessFile(tempFile, "rws"); // 创建临时文件, 用来记录每个线程已下载多少
120-
for (int i = 0; i < THREAD_AMOUNT; i++) // 按照线程数循环
121-
raf.writeLong(0); // 写入每个线程的开始位置(都是从0开始)
137+
if (!tempFile.exists()) {
138+
RandomAccessFile raf = new RandomAccessFile(tempFile, "rws");
139+
for (int i = 0; i < THREAD_AMOUNT; i++)
140+
raf.writeLong(0);
122141
raf.close();
123142
}
124143

125-
for (int i = 0; i < THREAD_AMOUNT; i++) // 按照线程数循环
126-
new DownloadThread(i).start(); // 开启线程, 每个线程将会下载一部分数据到本地文件中
144+
for (int i = 0; i < THREAD_AMOUNT; i++) {
145+
new DownloadThread(i).start();
146+
}
127147

128-
begin = System.currentTimeMillis(); // 记录开始时间
148+
// 记录开始时间
149+
begin = System.currentTimeMillis();
129150
}
130151

131152
private class DownloadThread extends Thread {
132-
private int id; // 用来标记当前线程是下载任务中的第几个线程
153+
// 用来标记当前线程是下载任务中的第几个线程
154+
private int id;
133155

134156
public DownloadThread(int id) {
135157
this.id = id;
136158
}
137159

138160
public void run() {
139161
try {
140-
RandomAccessFile tempRaf = new RandomAccessFile(tempFile, "rws"); // 用来记录下载进度的临时文件
141-
tempRaf.seek(id * 8); // 将指针移动到当前线程的位置(每个线程写1个long值, 占8字节)
142-
long threadFinish = tempRaf.readLong(); // 读取当前线程已完成了多少
143-
synchronized(BreakpointDownloader.this) { // 多个下载线程之间同步
144-
totalFinish += threadFinish; // 统计所有线程总共完成了多少
162+
RandomAccessFile tempRaf = new RandomAccessFile(tempFile, "rws");
163+
tempRaf.seek(id * 8);
164+
long threadFinish = tempRaf.readLong();
165+
synchronized(BreakpointDownloader.this) {
166+
totalFinish += threadFinish;
145167
}
146168

147-
long start = id * threadLen + threadFinish; // 计算当前线程的起始位置
148-
long end = id * threadLen + threadLen - 1; // 计算当前线程的结束位置
169+
long start = id * threadLen + threadFinish;
170+
long end = id * threadLen + threadLen - 1;
149171
System.out.println("线程" + id + ": " + start + "-" + end);
150172

151173
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
152174
conn.setConnectTimeout(3000);
153-
conn.setRequestProperty("Range", "bytes=" + start + "-" + end); // 设置当前线程下载的范围
175+
conn.setRequestProperty("Range", "bytes=" + start + "-" + end);
154176

155-
InputStream in = conn.getInputStream(); // 获取连接的输入流
156-
RandomAccessFile dataRaf = new RandomAccessFile(dataFile, "rws"); // 装载数据的本地文件(可以理解为输出流)
157-
dataRaf.seek(start); // 设置当前线程保存数据的位置
177+
InputStream in = conn.getInputStream();
178+
RandomAccessFile dataRaf = new RandomAccessFile(dataFile, "rws");
179+
dataRaf.seek(start);
158180

159-
byte[] buffer = new byte[1024 * 100]; // 每次拷贝100KB
181+
byte[] buffer = new byte[1024 * 100];
160182
int len;
161183
while ((len = in.read(buffer)) != -1) {
162-
dataRaf.write(buffer, 0, len); // 从服务端读取数据, 写到本地文件
163-
threadFinish += len; // 每次写入数据之后, 统计当前线程完成了多少
164-
tempRaf.seek(id * 8); // 将临时文件的指针指向当前线程的位置
165-
tempRaf.writeLong(threadFinish); // 将当前线程完成了多少写入到临时文件
166-
synchronized(BreakpointDownloader.this) { // 多个下载线程之间同步
167-
totalFinish += len; // 统计所有线程总共完成了多少
184+
dataRaf.write(buffer, 0, len);
185+
threadFinish += len;
186+
tempRaf.seek(id * 8);
187+
tempRaf.writeLong(threadFinish);
188+
synchronized(BreakpointDownloader.this) {
189+
totalFinish += len;
168190
}
169191
}
170192
dataRaf.close();
171193
tempRaf.close();
172194

173195
System.out.println("线程" + id + "下载完毕");
174-
if (totalFinish == totalLen) { // 如果已完成长度等于服务端文件长度(代表下载完成)
196+
// 如果已完成长度等于服务端文件长度(代表下载完成)
197+
if (totalFinish == totalLen) {
175198
System.out.println("下载完成, 耗时: " + (System.currentTimeMillis() - begin));
176-
tempFile.delete(); // 删除临时文件
199+
// 删除临时文件
200+
tempFile.delete();
177201
}
178202
} catch (IOException e) {
179203
e.printStackTrace();

BasicKnowledge/屏幕适配.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
也就是说`UI`最终的pixel值只受像素密度dip的影响,
5454
这个`dip`就相当于那个换算系数,这个系数的值是多少有设备商去决定。因此`dip`符合这种要求。
5555

56-
##android为什么引进dip
56+
## android为什么引进dip
5757

5858
> The reason for dip to exist is simple enough. Take for instance the T-Mobile G1. It has a pixel resolution of 320x480 pixels.
5959
Now image another device, with the same physical screen size, but more pixels, for instance 640x480.
@@ -206,7 +206,7 @@ UI给工程师切多大图是合适的。
206206
这样系统会在不同密度屏幕的手机中对图片进行合理的缩放,如果想在`xxhdpi`的手机上显示的很好, 也可以基于`1080P`的屏幕设计然后放到`xxhdpi`中,
207207
这样的话就兼容所有低密度屏幕的手机, 而且也不会出现图片被拉扯的现象。
208208

209-
***Note:***` The mipmap-xxxhdpi qualifier is necessary only to provide a launcher icon that can appear larger than usual on an xxhdpi device. You do not need to provide xxxhdpi assets for all your app's images.`
209+
Note:`The mipmap-xxxhdpi qualifier is necessary only to provide a launcher icon that can appear larger than usual on an xxhdpi device. You do not need to provide xxxhdpi assets for all your app's images.`
210210

211211

212212

Gradle&Maven/Gradle专题.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ android {
5252
```
5353

5454

55-
- `buildscript { ... }`配置了编译时的代码驱动. 这种情况下,它声明所使用的是`jCenter`仓库。还有一个声明所依赖的在`Maven`文件的路径。这里声明的包含了`Android`插件所使用的1.5.0版本的`Gradle`. ***注意:***这只会影响`build`中运行的代码,不是项目中。项目中需要声明它自己所需要仓库和依赖关系。
55+
- `buildscript { ... }`配置了编译时的代码驱动. 这种情况下,它声明所使用的是`jCenter`仓库。还有一个声明所依赖的在`Maven`文件的路径。这里声明的包含了`Android`插件所使用的1.5.0版本的`Gradle`. 注意:这只会影响`build`中运行的代码,不是项目中。项目中需要声明它自己所需要仓库和依赖关系。
5656
- `apply plugin : com.android.application`,声明使用`com.androdi.application`插件。这是构建`Android`应用所需要的插件。
5757
- `android{...}`配置了所有`Android`构建时的参数。默认情况下,只有编译的目标版本以及编译工具的版本是需要的。
5858

@@ -91,7 +91,7 @@ android {
9191
}
9292
```
9393
就像有些人就是要把`so`放到`libs`目录中(这类人有点犟),那就需要这样进行修改。
94-
***注意:***因为在旧的项目结构中所有的源文件(`Java`,`AIDL``RenderScript`)都放到同一个目录中,我们需要将`sourceSet`中的这些新部件都设置给`src`目录。
94+
注意:因为在旧的项目结构中所有的源文件(`Java`,`AIDL``RenderScript`)都放到同一个目录中,我们需要将`sourceSet`中的这些新部件都设置给`src`目录。
9595

9696
Build Tasks
9797
---
@@ -108,7 +108,7 @@ Build Tasks
108108
- `assembleDebug`
109109
- `assembleRelease`
110110

111-
***提示:***`Gradle`支持通过命令行执行任务首字母缩写的方式。例如:
111+
提示:`Gradle`支持通过命令行执行任务首字母缩写的方式。例如:
112112
在没有其他任务符合`aR`的前提下,`gradle aR``gradle assembleRelease`是相同的。
113113

114114
最后,构建插件创建了为所有`build type(debug, release, test)`类型安装和卸载的任务,只要他们能被安装(需要签名)。
@@ -157,7 +157,7 @@ android {
157157
}
158158
}
159159
```
160-
***注意:***不要使用可能与现有给定冲突的方法名。例如`defaultConfig{...}`中使用`getVersionName()`方法将会自动使用`defaultConfig.getVersionName()`来带起自定义的方法。
160+
注意:不要使用可能与现有给定冲突的方法名。例如`defaultConfig{...}`中使用`getVersionName()`方法将会自动使用`defaultConfig.getVersionName()`来带起自定义的方法。
161161

162162
##### `Build Types`
163163

@@ -249,7 +249,7 @@ android {
249249
...
250250
}
251251
```
252-
***注意:***`DSL`元素中的`dependencies``Gradle API`中的标准元素。不属于`andorid`元素。
252+
注意:`DSL`元素中的`dependencies``Gradle API`中的标准元素。不属于`andorid`元素。
253253
`compile`配置是用来编译主应用的。它配置的所有部分都会被打包到`apk`中。当然也有一些其他的配置:
254254

255255
- `compile`: `main application`
@@ -279,8 +279,8 @@ android {
279279
}
280280
```
281281

282-
***注意: ***`jcenter()`是指定仓库`URL`的快捷设置。`Gradle`支持远程和本地仓库。
283-
***注意: ***`Gradle`会直接识别所有的依赖关系。这就意味着如果一个依赖库自身又依赖别的库时,他们会被一起下下来。
282+
注意:`jcenter()`是指定仓库`URL`的快捷设置。`Gradle`支持远程和本地仓库。
283+
注意:`Gradle`会直接识别所有的依赖关系。这就意味着如果一个依赖库自身又依赖别的库时,他们会被一起下下来。
284284

285285
##### 本地`AAR`
286286

ImageLoaderLibrary/Glide简介(上).md

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ Glide简介(上)
1212

1313
- 使用简单
1414
- 可配置度高,自适应程度高
15-
- 支持`gif``webp`
1615
- 支持多种数据源,网络、本地、资源、`Assets`
1716
- 支持`Gif`图片。
1817
- 支持`WebP`
@@ -103,7 +102,7 @@ dependencies {
103102
```
104103

105104

106-
###接下来是一些常用的方法:
105+
### 接下来是一些常用的方法:
107106

108107
- 从网络加载图片
109108

ImageLoaderLibrary/Glide简介(下).md

+1-1
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ builder.setDiskCache(
411411
//);
412412
```
413413

414-
###缓存总结
414+
### 缓存总结
415415

416416
通过上面的设置可以发现,`Glide`一共使用了三种缓存方式:
417417

0 commit comments

Comments
 (0)