Retrofit2的再封裝實戰(zhàn)—多線程下載與斷點續(xù)傳(一)

這篇真的要升天啦
這篇真的要升天啦

前言

先感謝大家對第一篇文章《Retrofit2的再封裝實戰(zhàn)—同步與異步請求》的支持城看,提筆之前反復(fù)考慮了很多女气,要怎么寫好多線程下載和斷點續(xù)傳?倒不是因為邏輯有多復(fù)雜测柠,是因為這里覆蓋的知識面太多了炼鞠,大量的多線程共享數(shù)據(jù),本地數(shù)據(jù)持久化轰胁,以及面向不同狀態(tài)如何反饋的問題谒主,這些東西每一塊其實都能掰碎了寫一寫,所以拼在一起赃阀,讓我不知道到底應(yīng)該從哪里入手開始寫霎肯。
既然上篇文章結(jié)尾說過了如果有人需要就分享這方面的封裝,為了不讓期待的朋友們失望榛斯。最后決定還是要硬著頭皮開始寫观游,至于從哪里開始寫,既然沒有好的想法驮俗,那就從頭開始懂缕,就當是重新寫一遍吧,如果在這過程中你有不通或者不認可的想法王凑,歡迎分享指正給我搪柑,大家一起進步吧。

(這篇文章是基于我的第一篇文章再拓展的索烹,所以建議您先移步上篇文章)

視頻演示:


monkey.gif

點下載有等待時間拌屏,是因為我設(shè)置了每下載1m才回調(diào)。

正題

基礎(chǔ)概念

一术荤、什么是多線程下載?

Android主線程是不建議阻塞的每篷,通常的思路瓣戚,我們下載文件,都是在線程中執(zhí)行焦读,一個線程對應(yīng)一個下載通道子库,如果文件有上百M大小,況且你的網(wǎng)絡(luò)狀態(tài)不夠好矗晃,應(yīng)該怎么辦呢仑嗅?想一下如果我們把一個100M的文件,拆成4個線程,同時下載仓技,那該是多么幸福的事情啊鸵贬。無論是效率還是時間上,都會有大幅度的提升脖捻。那么在http上怎么實現(xiàn)分段下載呢阔逼?很簡單 在請求頭上加入Range屬性,像這樣設(shè)置bytes范圍就可以了地沮。


Range.png

現(xiàn)在Response Body就會返回對應(yīng)范圍的字節(jié)流了嗜浮。好了,現(xiàn)在我們來拓展NetWorkRequest類摩疑,加入Download接口危融。

   @Streaming   
   @GET    
  Call<ResponseBody> downloadFile(@Url String fileUrl,@Header("Range") String range);
}```
在NetWorkRequest中的中加入獲得DownLoadService接口代理類的方法,在init中初始化DownLoadService:
```mDownLoadService = mRetrofit.create(DownLoadService.class);```
向外提供mDownLoadService引用:
```public DownLoadService getDownLoadService() {
    return mDownLoadService;
}```
好了雷袋,關(guān)于DownLoadService的初始化就結(jié)束了吉殃。

#####二、什么是斷點續(xù)傳片排?
簡單解釋就是 從哪摔倒的接著從哪站起來 這就意味著我們可以做取消寨腔、繼續(xù)下載的功能,或者從異常情況下恢復(fù)的再下載功能率寡。
關(guān)于如何保持下載數(shù)據(jù)問題迫卢,其實就是如何選擇數(shù)據(jù)持久化方式的問題。
Android數(shù)據(jù)持久化方式 Preferences  SQL  I/O ContentProvider冶共,這里選擇SQL應(yīng)該是沒有任何異議的乾蛤,至于你是選擇如何實現(xiàn)SQL功能,GreenDao還是Realm或者其他開源項目捅僵,這里不做推薦家卖,只要能夠?qū)崿F(xiàn)簡單的增刪改查功能就好,我選擇了原生的sqllite庙楚。只為了實現(xiàn)簡單功能上荡,并未做完整封裝,不考慮借鑒我的sqllite馒闷。

####程序結(jié)構(gòu)
介紹了基本概念的理解酪捡,相信大家對本次實戰(zhàn)的內(nèi)容應(yīng)該有大體了解了。下面上簡單的項目結(jié)構(gòu)圖并說一下思路:
![結(jié)構(gòu)圖.jpeg](http://upload-images.jianshu.io/upload_images/3376157-c16a695249dde192.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
Action:為行動的意思纳账,這里代表我們的Activity逛薇,F(xiàn)ragment,或者是Service疏虫。A永罚、B即代表著兩次請求行為。

DownLoadManager:不同的Action呢袱,通過統(tǒng)一入口DownLoadManager調(diào)用下載功能官扣,DownLoadManager是單列的。只提供唯一入口醇锚,就像很多開源框架Glide.with()、ImageLoader.load()一樣焊唬,這里是一個設(shè)計思路挟炬,外觀模式,也稱為門面模式谤祖,大家設(shè)計框架時候盡量這樣來做婿滓,只提供一個入口凸主,即為了以后好維護,也減少了耦合性额湘。我們里面代碼再怎么修改卿吐,也并不影響外面的調(diào)用。不要改一動全身那就尷尬了锋华。DownLoadManager提供創(chuàng)建createRequest方法嗡官,我們把每個Action的所有下載任務(wù)封裝為一個Request,DownLoadManager中只負責(zé)創(chuàng)建和取消下載任務(wù)毯焕,并維護下載任務(wù)的緩存衍腥。

Request:上面說道,Request即為一次下載任務(wù)纳猫。每個Request里面可能有幾十紧阔,甚至上百個url,每個url可能又會因為數(shù)據(jù)太大而分為多線程任務(wù)续担。每個Request里面維護著所有任務(wù)的緩存,基本的邏輯判斷活孩,數(shù)據(jù)持久化都在Request里面物遇,所以這是最有含金量的部分,怎么做到性能最優(yōu),怎么做到多線程數(shù)據(jù)的安全性询兴,都在這里面乃沙。

Task:每個url即為一個Task,通過Retrofit調(diào)用DownLoad接口诗舰,并進行數(shù)據(jù)存儲操作警儒,這里并沒有什么難度,只需要通過判斷不用的情況眶根,返回不通的狀態(tài)值蜀铲,對數(shù)據(jù)進行不同的操作。同時属百,根據(jù)你的業(yè)務(wù)邏輯记劝,來適配不通IOException行為。

簡單來講族扰,入口類DownLoadManager厌丑,調(diào)用者只需要關(guān)心這一個類,創(chuàng)建下載任務(wù)渔呵,DownLoadManager把每個任務(wù)封裝成一個Request對象怒竿,復(fù)雜的邏輯判斷全部交給Request來做,Task是真正執(zhí)行下載任務(wù)的對象扩氢,數(shù)據(jù)回調(diào)從下向上依次傳遞回Action耕驰。

####文章計劃
寫到這里,我想我介紹的思路應(yīng)該已經(jīng)很清晰了类茂,本次內(nèi)容分為三個部分介紹耍属。第一部分到這就結(jié)束了,只要是講一下概念和思路和DownloadService的初始化巩检,覺得有意思的朋友可以根據(jù)我上文說的思路厚骗,設(shè)計一下。下面兩篇文章是這樣計劃的兢哭,第二篇從DownloadTask和DownloadManager入口领舰,最后一篇放到重要的Request上,如果您感興趣迟螺,可以關(guān)注下這個系列冲秽。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市矩父,隨后出現(xiàn)的幾起案子锉桑,更是在濱河造成了極大的恐慌,老刑警劉巖窍株,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件民轴,死亡現(xiàn)場離奇詭異攻柠,居然都是意外死亡,警方通過查閱死者的電腦和手機后裸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門瑰钮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人微驶,你說我怎么就攤上這事浪谴。” “怎么了因苹?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵苟耻,是天一觀的道長。 經(jīng)常有香客問我容燕,道長梁呈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任蘸秘,我火速辦了婚禮官卡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘醋虏。我一直安慰自己寻咒,他們只是感情好,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布颈嚼。 她就那樣靜靜地躺著毛秘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪阻课。 梳的紋絲不亂的頭發(fā)上叫挟,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音限煞,去河邊找鬼抹恳。 笑死,一個胖子當著我的面吹牛署驻,可吹牛的內(nèi)容都是我干的奋献。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼旺上,長吁一口氣:“原來是場噩夢啊……” “哼瓶蚂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起宣吱,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤窃这,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后征候,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钦听,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡洒试,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了朴上。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡卒煞,死狀恐怖痪宰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情畔裕,我是刑警寧澤衣撬,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站扮饶,受9級特大地震影響具练,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜甜无,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一扛点、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧岂丘,春花似錦陵究、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至寨蹋,卻和暖如春松蒜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背已旧。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工秸苗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人评姨。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓难述,卻偏偏與公主長得像,于是被迫代替她去往敵國和親吐句。 傳聞我的和親對象是個殘疾皇子胁后,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容