Commit b8d6e50931eb3977a9bbcd1c1490ef427e5995cc

Authored by 韩亚云
1 parent 5921ea59

提交补充

Showing 1 changed file with 51 additions and 465 deletions
README.md
@@ -2,8 +2,6 @@ @@ -2,8 +2,6 @@
2 Android OkHttp 銝蝸憭葵辣 銝蝸 2 Android OkHttp 銝蝸憭葵辣 銝蝸
3 ## 隞 3 ## 隞
4 demo蜓閬餉嚗okhttp RxJava 摮瑪蝔葉銝蝸辣嚗閫芋撘銝蝸漲嚗銝餌瑪蝔葉嚗EventBus 憿菟嚗餈漲 4 demo蜓閬餉嚗okhttp RxJava 摮瑪蝔葉銝蝸辣嚗閫芋撘銝蝸漲嚗銝餌瑪蝔葉嚗EventBus 憿菟嚗餈漲
5 -##  
6 -![download.gif](https://upload-images.jianshu.io/upload_images/3183047-18efb4a2a30a86f2.gif?imageMogr2/auto-orient/strip)  
7 ### step1 撖澆靘 5 ### step1 撖澆靘
8 ```Java 6 ```Java
9 // OKHttp RxJava 7 // OKHttp RxJava
@@ -13,354 +11,66 @@ demo蜓閬餉嚗okhttp RxJava 摮瑪蝔葉銝蝸辣嚗 @@ -13,354 +11,66 @@ demo蜓閬餉嚗okhttp RxJava 摮瑪蝔葉銝蝸辣嚗
13 // eventbus 11 // eventbus
14 implementation 'org.greenrobot:eventbus:3.0.0' 12 implementation 'org.greenrobot:eventbus:3.0.0'
15 implementation 'com.android.support:recyclerview-v7:27.1.1' 13 implementation 'com.android.support:recyclerview-v7:27.1.1'
  14 + implementation 'com.google.code.gson:gson:2.8.1'
  15 + //靽
  16 + implementation 'org.greenrobot:greendao:3.2.2'
16 ``` 17 ```
17 ### step 2 摰蝸bean 18 ### step 2 摰蝸bean
18 -```Java  
19 -/**  
20 - * Created by zs  
21 - * Date嚗2018撟 09 12  
22 - * Time嚗13:50  
23 - *  
24 - * About: 銝蝸蝞∠  
25 - *  
26 - */  
27 -public class DownloadInfo {  
28 -  
29 - /**  
30 - * 銝蝸  
31 - */  
32 - public static final String DOWNLOAD = "download";  
33 - public static final String DOWNLOAD_PAUSE = "pause";  
34 - public static final String DOWNLOAD_CANCEL = "cancel";  
35 - public static final String DOWNLOAD_OVER = "over";  
36 - public static final String DOWNLOAD_ERROR = "error";  
37 -  
38 - public static final long TOTAL_ERROR = -1;//漲憭梯揖  
39 -  
40 - private String url;  
41 - private String fileName;  
42 - private String downloadStatus;  
43 - private long total;  
44 - private long progress;  
45 -  
46 - public DownloadInfo(String url) {  
47 - this.url = url;  
48 - }  
49 -  
50 - public String getUrl() {  
51 - return url;  
52 - }  
53 -  
54 - public String getFileName() {  
55 - return fileName;  
56 - }  
57 -  
58 - public void setFileName(String fileName) {  
59 - this.fileName = fileName;  
60 - } 19 +```Java DownloadInfo
61 20
62 - public long getTotal() {  
63 - return total;  
64 - }  
65 -  
66 - public void setTotal(long total) {  
67 - this.total = total;  
68 - }  
69 -  
70 - public long getProgress() {  
71 - return progress;  
72 - }  
73 -  
74 - public void setProgress(long progress) {  
75 - this.progress = progress;  
76 - }  
77 -  
78 - public String getDownloadStatus() {  
79 - return downloadStatus;  
80 - }  
81 -  
82 - public void setDownloadStatus(String downloadStatus) {  
83 - this.downloadStatus = downloadStatus;  
84 - }  
85 -} 21 +### step 3 DownLoadService 撘銝銝芣嚗嚗蝸嚗
86 22
87 -```  
88 -### step 3 銝蝸蝞∠掩 銋銝餉捆 嚗ownloadManager嚗 23 +### step 4 銝蝸蝞∠掩 銋銝餉捆 嚗ownloadManager嚗雿靽瘜
89 ```Java 24 ```Java
90 -/**  
91 - * Created by zs  
92 - * Date嚗2018撟 09 12  
93 - * Time嚗13:56  
94 - *  
95 - * About: 銝蝸蝞∠  
96 - *  
97 - */  
98 -public class DownloadManager {  
99 -  
100 - private static final AtomicReference<DownloadManager> INSTANCE = new AtomicReference<>();  
101 - private OkHttpClient mClient;  
102 - private HashMap<String, Call> downCalls; //摮葵銝蝸窈瘙  
103 -  
104 - public static DownloadManager getInstance() {  
105 - for (; ; ) {  
106 - DownloadManager current = INSTANCE.get();  
107 - if (current != null) {  
108 - return current;  
109 - }  
110 - current = new DownloadManager();  
111 - if (INSTANCE.compareAndSet(null, current)) {  
112 - return current;  
113 - }  
114 - }  
115 - }  
116 -  
117 - private DownloadManager() {  
118 - downCalls = new HashMap<>();  
119 - mClient = new OkHttpClient.Builder().build();  
120 - }  
121 -  
122 - /**  
123 - * 銝蝸隞餃銝  
124 - * @param url  
125 - * @return  
126 - */  
127 - public boolean getDownloadUrl(String url){  
128 - return downCalls.containsKey(url);  
129 - }  
130 -  
131 - /**  
132 - * 撘憪蝸  
133 - *  
134 - * @param url 銝蝸霂瑟  
135 - * @param downLoadObserver  
136 - */  
137 - public void download(String url, DownloadObserver downLoadObserver) {  
138 -  
139 - Observable.just(url)  
140 - .filter(new Predicate<String>() {  
141 - @Override  
142 - public boolean test(String s) {  
143 - return !downCalls.containsKey(s);  
144 - }  
145 - }) // 餈誘 callap銝剖歇蝏,撠梯迤銝蝸,活銝蝸  
146 - .flatMap(new Function<String, ObservableSource<?>>() {  
147 - @Override  
148 - public ObservableSource<?> apply(String s) {  
149 - return Observable.just(createDownInfo(s));  
150 - }  
151 - }) // DownloadInfo  
152 - .map(new Function<Object, DownloadInfo>() {  
153 - @Override  
154 - public DownloadInfo apply(Object o) {  
155 - return getRealFileName((DownloadInfo)o);  
156 - }  
157 - }) // 憒歇蝏蝸嚗  
158 - .flatMap(new Function<DownloadInfo, ObservableSource<DownloadInfo>>() {  
159 - @Override  
160 - public ObservableSource<DownloadInfo> apply(DownloadInfo downloadInfo) {  
161 - return Observable.create(new DownloadSubscribe(downloadInfo));  
162 - }  
163 - }) // 銝蝸  
164 - .observeOn(AndroidSchedulers.mainThread()) // 銝餌瑪蝔葉  
165 - .subscribeOn(Schedulers.io()) // 摮瑪蝔葉銵  
166 - .subscribe(downLoadObserver); // 瘛餃銝蝸餈漲  
167 - }  
168 -  
169 - /**  
170 - * 銝蝸  
171 - * @param url  
172 - */  
173 - public void pauseDownload(String url) {  
174 - Call call = downCalls.get(url);  
175 - if (call != null) {  
176 - call.cancel();//  
177 - }  
178 - downCalls.remove(url);  
179 - }  
180 -  
181 - /**  
182 - * 蝸 辣  
183 - * @param info  
184 - */  
185 - public void cancelDownload(DownloadInfo info){  
186 - pauseDownload(info.getUrl());  
187 - info.setProgress(0);  
188 - info.setDownloadStatus(DownloadInfo.DOWNLOAD_CANCEL);  
189 - EventBus.getDefault().post(info);  
190 - Constant.deleteFile(info.getFileName());  
191 - }  
192 -  
193 - /**  
194 - * 遣DownInfo  
195 - *  
196 - * @param url 霂瑟  
197 - * @return DownInfo  
198 - */  
199 - private DownloadInfo createDownInfo(String url) {  
200 - DownloadInfo downloadInfo = new DownloadInfo(url);  
201 - long contentLength = getContentLength(url);//敺辣憭批  
202 - downloadInfo.setTotal(contentLength);  
203 - String fileName = url.substring(url.lastIndexOf("/"));  
204 - downloadInfo.setFileName(fileName);  
205 - return downloadInfo;  
206 - }  
207 -  
208 - /**  
209 - * 憒辣撌脖蝸辣  
210 - * @param downloadInfo  
211 - * @return  
212 - */  
213 - private DownloadInfo getRealFileName(DownloadInfo downloadInfo) {  
214 - String fileName = downloadInfo.getFileName();  
215 - long downloadLength = 0, contentLength = downloadInfo.getTotal();  
216 - File path = new File(Constant.FILE_PATH);  
217 - if (!path.exists()) {  
218 - path.mkdir();  
219 - }  
220 - File file = new File(Constant.FILE_PATH, fileName);  
221 - if (file.exists()) {  
222 - //鈭辣,隞”撌脩蝸餈,摨  
223 - downloadLength = file.length();  
224 - }  
225 - //銋蝸餈,閬銝銝芣辣  
226 - int i = 1;  
227 - while (downloadLength >= contentLength) {  
228 - int dotIndex = fileName.lastIndexOf(".");  
229 - String fileNameOther;  
230 - if (dotIndex == -1) {  
231 - fileNameOther = fileName + "(" + i + ")";  
232 - } else {  
233 - fileNameOther = fileName.substring(0, dotIndex)  
234 - + "(" + i + ")" + fileName.substring(dotIndex);  
235 - }  
236 - File newFile = new File(Constant.FILE_PATH, fileNameOther);  
237 - file = newFile;  
238 - downloadLength = newFile.length();  
239 - i++;  
240 - }  
241 - //霈曄蔭辣/憭批  
242 - downloadInfo.setProgress(downloadLength);  
243 - downloadInfo.setFileName(file.getName());  
244 - return downloadInfo;  
245 - }  
246 -  
247 - private class DownloadSubscribe implements ObservableOnSubscribe<DownloadInfo> {  
248 - private DownloadInfo downloadInfo;  
249 -  
250 - public DownloadSubscribe(DownloadInfo downloadInfo) {  
251 - this.downloadInfo = downloadInfo;  
252 - }  
253 -  
254 - @Override  
255 - public void subscribe(ObservableEmitter<DownloadInfo> e) throws Exception {  
256 - String url = downloadInfo.getUrl();  
257 - long downloadLength = downloadInfo.getProgress();//撌脩蝸憟賜摨  
258 - long contentLength = downloadInfo.getTotal();//辣駁摨  
259 - //漲靽⊥  
260 - e.onNext(downloadInfo);  
261 - Request request = new Request.Builder()  
262 - //蝖桀蝸,瘛餃迨憭,撠勗隞亥歲餈歇蝏蝸憟賜  
263 - .addHeader("RANGE", "bytes=" + downloadLength + "-" + contentLength)  
264 - .url(url)  
265 - .build();  
266 - Call call = mClient.newCall(request);  
267 - downCalls.put(url, call);//葵瘛餃call,靘踹  
268 - Response response = call.execute();  
269 - File file = new File(Constant.FILE_PATH, downloadInfo.getFileName());  
270 - InputStream is = null;  
271 - FileOutputStream fileOutputStream = null;  
272 - try {  
273 - is = response.body().byteStream();  
274 - fileOutputStream = new FileOutputStream(file, true);  
275 - byte[] buffer = new byte[2048];//蝻蝏2kB  
276 - int len;  
277 - while ((len = is.read(buffer)) != -1) {  
278 - fileOutputStream.write(buffer, 0, len);  
279 - downloadLength += len;  
280 - downloadInfo.setProgress(downloadLength);  
281 - e.onNext(downloadInfo);  
282 - }  
283 - fileOutputStream.flush();  
284 - downCalls.remove(url);  
285 - } finally {  
286 - //IO瘚  
287 - DownloadIO.closeAll(is, fileOutputStream);  
288 -  
289 - }  
290 - e.onComplete();//摰  
291 - }  
292 - }  
293 -  
294 - /**  
295 - * 蝸摨  
296 - *  
297 - * @param downloadUrl  
298 - * @return  
299 - */  
300 - private long getContentLength(String downloadUrl) {  
301 - Request request = new Request.Builder()  
302 - .url(downloadUrl)  
303 - .build();  
304 - try {  
305 - Response response = mClient.newCall(request).execute();  
306 - if (response != null && response.isSuccessful()) {  
307 - long contentLength = response.body().contentLength();  
308 - response.close();  
309 - return contentLength == 0 ? DownloadInfo.TOTAL_ERROR : contentLength;  
310 - }  
311 - } catch (IOException e) {  
312 - e.printStackTrace();  
313 - }  
314 - return DownloadInfo.TOTAL_ERROR;  
315 - } 25 + public void download(final DownloadInfo downloadInfo) {
  26 + List<DownloadInfo> list = MyApplication.getInstances().getDaoSession().loadAll(DownloadInfo.class);
  27 + downWait.clear();
  28 + downWait = list;
  29 + if (currentDownInfo != null) pauseDownload(currentDownInfo, true);
  30 + if (downCalls.containsKey(downloadInfo.getUrl())) downCalls.remove(downloadInfo.getUrl());
  31 + Observable.just(downloadInfo.getUrl())
  32 + .filter(new Predicate<String>() { // 餈誘 callap銝剖歇蝏,撠梯迤銝蝸,活銝蝸
  33 + @Override
  34 + public boolean test(String s) {
  35 + boolean flag = downCalls.containsKey(s);
  36 + if (flag) {
  37 + // 憒歇蝏銝蝸嚗僎銝嚗銝銝芣辣餈蝸
  38 + downNext();
  39 + return false;
  40 + } else {
  41 + // 憒迤銝蝸葵颲曉憭折嚗蝑蝸”銝
  42 + return true;
  43 + }
  44 + }
  45 + })
  46 + .flatMap(new Function<String, ObservableSource<?>>() { // DownloadInfo
  47 + @Override
  48 + public ObservableSource<?> apply(String s) {
  49 + return Observable.just(createDownInfo(downloadInfo));
  50 + }
  51 + })
  52 + .map(new Function<Object, DownloadInfo>() { // 憒歇蝏蝸嚗
  53 + @Override
  54 + public DownloadInfo apply(Object o) {
  55 + return getRealFileName((DownloadInfo) o);
  56 + }
  57 + })
  58 + .flatMap(new Function<DownloadInfo, ObservableSource<DownloadInfo>>() { // 銝蝸
  59 + @Override
  60 + public ObservableSource<DownloadInfo> apply(DownloadInfo downloadInfo) {
  61 + currentDownInfo = downloadInfo;
  62 + return Observable.create(new DownloadSubscribe(downloadInfo));
  63 + }
  64 + })
  65 + .observeOn(AndroidSchedulers.mainThread()) // 銝餌瑪蝔葉
  66 + .subscribeOn(Schedulers.io()) // 摮瑪蝔葉銵
  67 + .subscribe(new DownloadLimitObserver()); // 瘛餃銝蝸餈漲
  68 + }
316 69
317 -}  
318 -```  
319 -餈銝蝸蝞∠掩芋撘敹◆摰銝杳ashMap摮蝸隞餃嚗ownload嚗瘜銝餉  
320 -```Java  
321 -public void download(String url, DownloadObserver downLoadObserver) {  
322 -  
323 - Observable.just(url)  
324 - .filter(new Predicate<String>() {  
325 - @Override  
326 - public boolean test(String s) {  
327 - return !downCalls.containsKey(s);  
328 - }  
329 - }) // 餈誘 callap銝剖歇蝏,撠梯迤銝蝸,活銝蝸  
330 - .flatMap(new Function<String, ObservableSource<?>>() {  
331 - @Override  
332 - public ObservableSource<?> apply(String s) {  
333 - return Observable.just(createDownInfo(s));  
334 - }  
335 - }) // DownloadInfo  
336 - .map(new Function<Object, DownloadInfo>() {  
337 - @Override  
338 - public DownloadInfo apply(Object o) {  
339 - return getRealFileName((DownloadInfo)o);  
340 - }  
341 - }) // 憒歇蝏蝸嚗  
342 - .flatMap(new Function<DownloadInfo, ObservableSource<DownloadInfo>>() {  
343 - @Override  
344 - public ObservableSource<DownloadInfo> apply(DownloadInfo downloadInfo) {  
345 - return Observable.create(new DownloadSubscribe(downloadInfo));  
346 - }  
347 - }) // 銝蝸  
348 - .observeOn(AndroidSchedulers.mainThread()) // 銝餌瑪蝔葉  
349 - .subscribeOn(Schedulers.io()) // 摮瑪蝔葉銵  
350 - .subscribe(downLoadObserver); // 瘛餃銝蝸餈漲  
351 - }  
352 ``` 70 ```
353 餈Rxjava嚗洵銝甇卯ilter嚗誘銝蝸嚗歇蝏蝸rl銝蝸銝韏瑚蝸隞餃洵鈭郊flatMap嚗rlean蝐鳴葵瘙霈曇恣嚗隞亦隡銝朋ean餈銋隞亦洵銝郊map嚗葵辣撌脩蝸鈭活銝蝸辣嚗瘙蝸餈辣銝閬蝸嚗停隞亦洵郊flatMap嚗銝蝸雿蝸瘜銝停蝥輻溶 71 餈Rxjava嚗洵銝甇卯ilter嚗誘銝蝸嚗歇蝏蝸rl銝蝸銝韏瑚蝸隞餃洵鈭郊flatMap嚗rlean蝐鳴葵瘙霈曇恣嚗隞亦隡銝朋ean餈銋隞亦洵銝郊map嚗葵辣撌脩蝸鈭活銝蝸辣嚗瘙蝸餈辣銝閬蝸嚗停隞亦洵郊flatMap嚗銝蝸雿蝸瘜銝停蝥輻溶
354 ### step4 閫 72 ### step4 閫
355 ```Java 73 ```Java
356 -/**  
357 - * Created by zs  
358 - * Date嚗2018撟 09 12  
359 - * Time嚗13:50  
360 - *  
361 - * About: 閫  
362 - *  
363 - */  
364 public class DownloadObserver implements Observer<DownloadInfo> { 74 public class DownloadObserver implements Observer<DownloadInfo> {
365 75
366 public Disposable d;//隞亦鈭釣 76 public Disposable d;//隞亦鈭釣
@@ -380,21 +90,11 @@ public class DownloadObserver implements Observer&lt;DownloadInfo&gt; { @@ -380,21 +90,11 @@ public class DownloadObserver implements Observer&lt;DownloadInfo&gt; {
380 90
381 @Override 91 @Override
382 public void onError(Throwable e) { 92 public void onError(Throwable e) {
383 - Log.d("My_Log","onError");  
384 - if (DownloadManager.getInstance().getDownloadUrl(downloadInfo.getUrl())){  
385 - DownloadManager.getInstance().pauseDownload(downloadInfo.getUrl());  
386 - downloadInfo.setDownloadStatus(DownloadInfo.DOWNLOAD_ERROR);  
387 - EventBus.getDefault().post(downloadInfo);  
388 - }else{  
389 - downloadInfo.setDownloadStatus(DownloadInfo.DOWNLOAD_PAUSE);  
390 - EventBus.getDefault().post(downloadInfo);  
391 - }  
392 93
393 } 94 }
394 95
395 @Override 96 @Override
396 public void onComplete() { 97 public void onComplete() {
397 - Log.d("My_Log","onComplete");  
398 if (downloadInfo != null){ 98 if (downloadInfo != null){
399 downloadInfo.setDownloadStatus(DownloadInfo.DOWNLOAD_OVER); 99 downloadInfo.setDownloadStatus(DownloadInfo.DOWNLOAD_OVER);
400 EventBus.getDefault().post(downloadInfo); 100 EventBus.getDefault().post(downloadInfo);
@@ -403,118 +103,4 @@ public class DownloadObserver implements Observer&lt;DownloadInfo&gt; { @@ -403,118 +103,4 @@ public class DownloadObserver implements Observer&lt;DownloadInfo&gt; {
403 } 103 }
404 104
405 ``` 105 ```
406 -餈EventBus憿菟銋隞乩嚗恥Activity嚗銝鈭誨嚗葵憿菟閬漲撠梢獄鈭  
407 -### step5 Activity Adapter  
408 -憿菟銝剜銝銝析ecyclerView嚗漱鈭餉敺秩銝嚗dapter嚗otifyItemChanged(i) 瘥活漲嚗notifyDataSetChanged()嚗蛹靚嚗紡銝剜隞嗥鈭辣銝末瘝⊥◤鈭銋銝芷憸隡嚗圾獢ecyclerView撠梯圾鈭  
409 -```Java  
410 -// tem  
411 - ((SimpleItemAnimator)recycler_view.getItemAnimator()).setSupportsChangeAnimations(false);  
412 -```  
413 -```Java  
414 -/**  
415 - * Created by zs  
416 - * Date嚗2018撟 09 11  
417 - * Time嚗18:06  
418 - *  
419 - * About:  
420 - *  
421 - */  
422 -public class DownloadAdapter extends RecyclerView.Adapter<DownloadAdapter.UploadHolder> {  
423 -  
424 - private List<DownloadInfo> mdata;  
425 -  
426 - public DownloadAdapter(List<DownloadInfo> mdata) {  
427 - this.mdata = mdata;  
428 - }  
429 -  
430 - /**  
431 - * 銝蝸餈漲  
432 - * @param info  
433 - */  
434 - public void updateProgress(DownloadInfo info){  
435 - for (int i = 0; i < mdata.size(); i++){  
436 - if (mdata.get(i).getUrl().equals(info.getUrl())){  
437 - mdata.set(i,info);  
438 - notifyItemChanged(i);  
439 - break;  
440 - }  
441 - }  
442 - }  
443 -  
444 - @Override  
445 - public UploadHolder onCreateViewHolder(ViewGroup parent, int viewType) {  
446 - View view = View.inflate(parent.getContext(), R.layout.item_download_layout,null);  
447 - return new UploadHolder(view);  
448 - }  
449 -  
450 - @Override  
451 - public void onBindViewHolder(UploadHolder holder, int position) {  
452 -  
453 - final DownloadInfo info = mdata.get(position);  
454 - if (DownloadInfo.DOWNLOAD_CANCEL.equals(info.getDownloadStatus())){  
455 - holder.main_progress.setProgress(0);  
456 - }else if (DownloadInfo.DOWNLOAD_OVER.equals(info.getDownloadStatus())){  
457 - holder.main_progress.setProgress(holder.main_progress.getMax());  
458 - }else {  
459 - if (info.getTotal() == 0){  
460 - holder.main_progress.setProgress(0);  
461 - }else {  
462 - float d = info.getProgress() * holder.main_progress.getMax() / info.getTotal();  
463 - holder.main_progress.setProgress((int) d);  
464 - }  
465 - }  
466 - holder.main_btn_down.setOnClickListener(new View.OnClickListener() {  
467 - @Override  
468 - public void onClick(View view) {  
469 - DownloadManager.getInstance().download(info.getUrl(), new DownloadObserver());  
470 - }  
471 - });  
472 -  
473 - holder.main_btn_pause.setOnClickListener(new View.OnClickListener() {  
474 - @Override  
475 - public void onClick(View view) {  
476 - DownloadManager.getInstance().pauseDownload(info.getUrl());  
477 - }  
478 - });  
479 -  
480 - holder.main_btn_cancel.setOnClickListener(new View.OnClickListener() {  
481 - @Override  
482 - public void onClick(View view) {  
483 - DownloadManager.getInstance().cancelDownload(info);  
484 - }  
485 - });  
486 - }  
487 -  
488 - @Override  
489 - public int getItemCount() {  
490 - return mdata.size();  
491 - }  
492 -  
493 - public class UploadHolder extends RecyclerView.ViewHolder{  
494 -  
495 - private ProgressBar main_progress;  
496 - private Button main_btn_down;  
497 - private Button main_btn_pause;  
498 - private Button main_btn_cancel;  
499 -  
500 - public UploadHolder(View itemView) {  
501 - super(itemView);  
502 - main_progress = itemView.findViewById(R.id.main_progress);  
503 - main_btn_down = itemView.findViewById(R.id.main_btn_down);  
504 - main_btn_pause = itemView.findViewById(R.id.main_btn_pause);  
505 - main_btn_cancel = itemView.findViewById(R.id.main_btn_cancel);  
506 - }  
507 - }  
508 -  
509 -}  
510 -  
511 -```  
512 -### github  
513 -https://github.com/QQzs/DownloadFile  
514 -  
515 -### 蝞銋血  
516 -https://www.jianshu.com/p/4bab2e9c577e  
517 -  
518 -嚗  
519 -https://blog.csdn.net/cfy137000/article/details/54838608  
520 -捆撠耨嚗之摰嗆撣桀 106 +餈EventBus憿菟