欧美+在线播放,蜜臀av在线,久久久99久久久国产自输拍,免费 黄 色 人成 视频 在 线,免费+国产+国产精品

 
您的位置:首頁 >  新聞中心 > 云通訊公告
  云通訊公告
 

Android官方架構(gòu)組件指南

來源:原創(chuàng)    時間:2017-10-18    瀏覽:0 次

此攻略適用于那些從前或現(xiàn)在進(jìn)行Android運(yùn)用的根底開發(fā),并期望了解和學(xué)習(xí)編寫Android程序的最佳實(shí)踐和架構(gòu)。經(jīng)過學(xué)習(xí)來構(gòu)建強(qiáng)壯的出產(chǎn)等級的運(yùn)用。

留意:此攻略默許你對Android開發(fā)有比較深的了解,熟知Android Framework。如果你還僅僅個Android開發(fā)新手,那么主張先學(xué)習(xí)下Android的根底知識。
?
Android程序員面對的問題

傳統(tǒng)的桌面運(yùn)用程序開發(fā)在大多數(shù)狀況下,發(fā)動器快捷辦法都有一個進(jìn)口點(diǎn),并作為一個單一的進(jìn)程運(yùn)轉(zhuǎn),但Android運(yùn)用程序的結(jié)構(gòu)更為雜亂。典型的Android運(yùn)用程序由多個運(yùn)用程序組件構(gòu)成,包含Activity,F(xiàn)ragment,Service,ContentProvider和Broadcast Receiver。

大多數(shù)這些運(yùn)用程序組件在Android操作體系運(yùn)用的AndroidManifest中聲明,以決議怎樣將運(yùn)用程序集成到設(shè)備上來為用戶供給完好的體會。盡管如前所述,桌面運(yùn)用程序傳統(tǒng)上是作為一個單一的進(jìn)程運(yùn)轉(zhuǎn)的,但正確編寫的Android運(yùn)用程序則需求更靈敏,由于用戶經(jīng)過設(shè)備上的不同運(yùn)用程序織造辦法,不斷切換流程和使命。

舉個比方,當(dāng)用戶在交際App上計(jì)劃共享一張相片,那么Android體系就會為此發(fā)動相機(jī)來完結(jié)此次懇求。此刻用戶脫離了交際App,可是這個用戶體會是無縫銜接的。相機(jī)可能又會觸發(fā)并發(fā)動文件辦理器來挑選相片。終究回到交際App并共享相片。此外,在此進(jìn)程中的任何時候,用戶可能會被打電話中止,并在完結(jié)電話后再回來共享相片。

在Android中,這種運(yùn)用間跳轉(zhuǎn)行為很常見,因而你的運(yùn)用有必要正確處理這些流程。請記住,移動設(shè)備是資源有限的,所以在任何時候,操作體系可能需求殺死一些運(yùn)用來為新的運(yùn)用騰出空間。

你的運(yùn)用程序的一切組件都能夠被獨(dú)自發(fā)動或無序發(fā)動,而且在任何時候由用戶或體系毀掉。由于運(yùn)用程序組件是時刻短的,它們的生命周期(創(chuàng)立和毀掉時)不受你的操控,因而你不該該將任何運(yùn)用程序數(shù)據(jù)或狀況存儲在運(yùn)用程序組件中,而且運(yùn)用程序組件不該彼此依靠。

常見的架構(gòu)原理
如果你無法運(yùn)用運(yùn)用程序組件來存儲運(yùn)用程序數(shù)據(jù)和狀況,應(yīng)怎樣構(gòu)建運(yùn)用程序?

在你的App開發(fā)中你應(yīng)該將重心放在分層上,如果將一切的代碼都寫在Activity或許Fragment中,那問題就大了。任何不是處理UI或跟操作體系交互的操作不該該放在這兩個類中。盡量堅(jiān)持它們代碼的精簡,這樣你能夠防止許多與生命周期相關(guān)的問題。記住你并不能掌控Activity和Fragment,他們僅僅在你的App和Android體系間起了橋梁的效果。任何時候,Android體系可能會依據(jù)用戶操作或其他要素(如低內(nèi)存)來收回它們。最好盡量削減對他們的依靠,以供給堅(jiān)實(shí)的用戶體會。

還有一點(diǎn)比較重要的就是耐久模型驅(qū)動UI。運(yùn)用耐久模型首要是由于當(dāng)你的UI被收回或許在沒有網(wǎng)絡(luò)的狀況下還能正常給用戶展現(xiàn)數(shù)據(jù)。模型是用來處理運(yùn)用數(shù)據(jù)的組件,它們獨(dú)立于運(yùn)用中的視圖和四大組件。因而模型的生命周期必定和UI是別離的。堅(jiān)持UI代碼的整齊,會讓你能更簡略的辦理和調(diào)整UI。讓你的運(yùn)用依據(jù)模型開發(fā)能夠很好的辦理你運(yùn)用的數(shù)據(jù)并是你的運(yùn)用更具測驗(yàn)性和持續(xù)性。

運(yùn)用架構(gòu)引薦
回到這篇文章的主題,來說說Android官方架構(gòu)組件(一下簡稱架構(gòu))。一下會介紹怎樣在你的運(yùn)用中實(shí)踐這一架構(gòu)形式。

留意:不可能存在某一種架構(gòu)辦法能夠完美合適任何場景。話雖如此,這種架構(gòu)應(yīng)該是大多數(shù)用例的杰出起點(diǎn)。如果你現(xiàn)已有了很好的Android運(yùn)用程序架構(gòu)辦法,請持續(xù)堅(jiān)持。

假定我們需求一個實(shí)際用戶材料的UI,該用戶的材料文件將運(yùn)用REST API從效勞端獲取。

構(gòu)建用戶界面

我們的這個用戶界面由一個UserProfileFragment.java文件和它的布局文件user_profile_layout.xml。

為了驅(qū)動UI,數(shù)據(jù)模型需求持有下面兩個數(shù)據(jù):

User ID:用戶的標(biāo)識符。最好運(yùn)用Fragment的參數(shù)將此信息傳遞到Fragment中。如果Android操作體系收回了Fragment,則會保存此信息,以便下次從頭發(fā)動運(yùn)用時,該ID可用。
User Object:傳統(tǒng)的Java目標(biāo),代表用戶的數(shù)據(jù)。
為此,我們新建一個承繼自ViewModel的名為UserProfileViewModel的模型來持有這個數(shù)據(jù)。

ViewModel供給特定UI組件的數(shù)據(jù),例如Activity和Fragment,并處理與數(shù)據(jù)處理事務(wù)部分的通訊,例如調(diào)用其他組件來加載數(shù)據(jù)或轉(zhuǎn)發(fā)用戶修正。ViewModel不了解View,而且不受UI的重建(如重由于旋轉(zhuǎn)而導(dǎo)致的Activity的重建)的影響。

現(xiàn)在我們有一下三個文件:

user_profile.xml: 視圖的布局文件。
UserProfileViewModel.java: 持有UI數(shù)據(jù)的模型。
UserProfileFragment.java: 用于顯現(xiàn)數(shù)據(jù)模型中的數(shù)據(jù)并和用戶進(jìn)行交互。
一下是詳細(xì)代碼(為了簡化,布局文件省掉)。



留意:上面的UserProfileFragment承繼自LifeCycleFragment而不是Fragment。當(dāng)Lifecycle的Api安穩(wěn)后,F(xiàn)ragment會默許完結(jié)LifeCycleOwner。

現(xiàn)在,我們有三個文件,我們怎樣銜接它們?究竟,當(dāng)ViewModel的用戶字段被設(shè)置時,我們需求一種通知UI的辦法。這兒就要說到LiveData了。

LiveData是一個可調(diào)查的數(shù)據(jù)持有者。它答應(yīng)運(yùn)用程序中的組件調(diào)查LiveData目標(biāo)持有的數(shù)據(jù),而不會在它們之間創(chuàng)立顯式和剛性的依靠途徑。LiveData還尊重你的運(yùn)用程序組件(Activity,F(xiàn)ragment,Service)的生命周期狀況,并做正確的作業(yè)以防止內(nèi)存走漏,然后你的運(yùn)用程序不會耗費(fèi)更多的內(nèi)存。

如果你現(xiàn)已運(yùn)用了想Rxjava活著Agrea這類第三方庫,那么你能夠運(yùn)用它們替代LiveData,不過你需求處理好它們與組件生命周期之間的聯(lián)系。

現(xiàn)在我們運(yùn)用LiveData來替代UserProfileViewModel中的User字段。所以Fragment能夠經(jīng)過調(diào)查它來更新數(shù)據(jù)。LiveData值得稱道的當(dāng)?shù)鼐驮谟谒巧芷诟兄?,?dāng)生命周期完畢是,其上的調(diào)查者會被即便整理。


然后將UserProfileFragment修正如下,調(diào)查數(shù)據(jù)并更新UI:


一旦用戶數(shù)據(jù)更新,onChanged回調(diào)將被調(diào)用然后UI會被改寫。

如果你了解一些運(yùn)用調(diào)查者形式第三方庫,你會覺得古怪,為什么沒有在Fragment的onStop()辦法中將調(diào)查者移除。關(guān)于LiveData來說這是沒有必要的,由于它是生命周期感知的,這意味著如果UI處于不活動狀況,它就不會調(diào)用調(diào)查者的回調(diào)來更新數(shù)據(jù)。而且在onDestroy后會主動移除。

我們也不需求處理任何視圖重建(如屏幕旋轉(zhuǎn))。ViewModel會主動康復(fù)重建前的數(shù)據(jù)。當(dāng)新的視圖被創(chuàng)立出來后,它會接收到與之前相同的ViewModel實(shí)例,而且調(diào)查者的回調(diào)會被馬上調(diào)用,更新最新的數(shù)據(jù)。這也是ViewModel為什么不能直接引證視圖目標(biāo),由于它的生命周期善于視圖目標(biāo)。

獲取數(shù)據(jù)

現(xiàn)在我們將視圖和模型銜接起來,可是模型該怎樣獲取數(shù)據(jù)呢?在這個比方中,我們假定運(yùn)用REST API從后臺獲取。我們將運(yùn)用Retrofit來向后臺懇求數(shù)據(jù)。

我們的retrofit類Webservice如下:


如果僅僅簡略的完結(jié),ViewModel能夠直接操作Webservice來獲取用戶數(shù)據(jù)。盡管這樣能夠正常作業(yè),但你的運(yùn)用無法確保它的后續(xù)迭代。由于這樣做將太多的職責(zé)讓ViewModel來承當(dāng),這樣就違反類之前講到的分層準(zhǔn)則。又由于ViewModel的生命周期是綁定在Activity和Fragment上的,所以當(dāng)UI被毀掉后如果丟掉一切數(shù)據(jù)將是很差的用戶體會。所以我們的ViewModel將和一個新的模塊進(jìn)行交互,這個模塊叫Repository。

Repository模塊擔(dān)任處理數(shù)據(jù)。它為運(yùn)用程序的其余部分供給了一個潔凈的API。他知道在數(shù)據(jù)更新時從哪里獲取數(shù)據(jù)和調(diào)用哪些API調(diào)用。你能夠?qū)⑺鼈円暈椴煌瑪?shù)據(jù)源(耐久性模型,Web效勞,緩存等)之間的中介者。

UserRepository類如下:


盡管repository模塊看上去沒有必要,但他起著重要的效果。它為App的其他部分籠統(tǒng)出了數(shù)據(jù)源?,F(xiàn)在我們的ViewModel并不知道數(shù)據(jù)是經(jīng)過WebService來獲取的,這意味著我們能夠隨意替換掉獲取數(shù)據(jù)的完結(jié)。

辦理組件間的依靠聯(lián)系

上面這種寫法能夠看出來UserRepository需求初始化Webservice實(shí)例,這盡管說起來簡略,但要完結(jié)的話還需求知道Webservice的詳細(xì)結(jié)構(gòu)辦法該怎樣寫。這將加大代碼的雜亂度,別的UserRepository可能并不是僅有運(yùn)用Webservice的目標(biāo),所以這種在內(nèi)部構(gòu)建Webservice實(shí)例顯然是不引薦的,下面有兩種形式來處理這個問題:

依靠注入:依靠注入答應(yīng)類界說它們的依靠聯(lián)系而不結(jié)構(gòu)它們。在運(yùn)轉(zhuǎn)時,另一個類擔(dān)任供給這些依靠聯(lián)系。我們主張?jiān)贏ndroid運(yùn)用程序中運(yùn)用Google的Dagger 2庫完結(jié)依靠注入。Dagger 2經(jīng)過遍歷依靠聯(lián)系樹主動構(gòu)建目標(biāo),并在依靠聯(lián)系上供給編譯時確保。
效勞定位器:效勞定位器供給了一個注冊表,其間類能夠獲取它們的依靠聯(lián)系而不是結(jié)構(gòu)它們。與依靠注入(DI)比較,完結(jié)起來相對簡略,因而如果您不了解DI,請改用Service Locator。
這些形式答應(yīng)你擴(kuò)展代碼,由于它們供給清晰的形式來辦理依靠聯(lián)系,而不會重復(fù)代碼或增加雜亂性。兩者都答應(yīng)交流完結(jié)進(jìn)行測驗(yàn);這是運(yùn)用它們的首要優(yōu)點(diǎn)之一。在這個比方中,我們將運(yùn)用Dagger 2來辦理依靠聯(lián)系。

銜接ViewModel和Repository

現(xiàn)在,我們的UserProfileViewModel能夠改寫成這樣:


緩存數(shù)據(jù)

上面的Repository盡管網(wǎng)絡(luò)懇求做了封裝,可是它依靠后臺數(shù)據(jù)源,所以存在缺乏。

上面的UserRepository完結(jié)的問題是,在獲取數(shù)據(jù)之后,它不會保存在任何當(dāng)?shù)?。如果用戶脫離UserProfileFragment偏從頭進(jìn)來,則運(yùn)用程序?qū)念^獲取數(shù)據(jù)。這是欠好的,有兩個原因:它糟蹋了名貴的網(wǎng)絡(luò)帶寬和迫運(yùn)用戶等候新的查詢完結(jié)。為了處理這個問題,我們將向我們的UserRepository增加一個新的數(shù)據(jù)源,它將把User目標(biāo)緩存在內(nèi)存中。如下:


耐久化數(shù)據(jù)

在當(dāng)時的完結(jié)中,如果用戶旋轉(zhuǎn)屏幕或脫離并回來到運(yùn)用程序,現(xiàn)有UI將當(dāng)即可見,由于Repository會從內(nèi)存中檢索數(shù)據(jù)??墒?,如果用戶脫離運(yùn)用程序,并在Android操作體系殺死進(jìn)程后幾小時后又會怎樣樣?

在現(xiàn)在的完結(jié)中,我們將需求從網(wǎng)絡(luò)中再次獲取數(shù)據(jù)。這不僅是一個糟糕的用戶體會,也是糟蹋,由于它將運(yùn)用移動數(shù)據(jù)來從頭獲取相同的數(shù)據(jù)。你以經(jīng)過緩存Web懇求來簡略地處理這個問題,但它會發(fā)作新的問題。如果懇求一個朋友列表而不是單個用戶,會發(fā)作什么狀況?那么你的運(yùn)用程序可能會顯現(xiàn)不共同的數(shù)據(jù),這是最令人困惑的用戶體會。例如,相同的用戶的數(shù)據(jù)可能會不同,由于朋友列表懇求和用戶懇求能夠在不同的時刻履行。你的運(yùn)用需求兼并他們,以防止顯現(xiàn)不共同的數(shù)據(jù)。

正確的處理辦法是運(yùn)用耐久模型。這時候Room就派上用場了。

Room是一個目標(biāo)映射庫,它供給本地數(shù)據(jù)耐久性和最少的樣板代碼。在編譯時,它依據(jù)形式驗(yàn)證每個查詢,然后過錯的SQL查詢會導(dǎo)致編譯時過錯,而不是運(yùn)轉(zhuǎn)時失利。Room籠統(tǒng)了運(yùn)用原始SQL表和查詢的一些根本完結(jié)細(xì)節(jié)。它還答應(yīng)調(diào)查數(shù)據(jù)庫數(shù)據(jù)(包含調(diào)集和銜接查詢)的更改,經(jīng)過LiveData目標(biāo)揭露這些更改。

要運(yùn)用Room我們首要需求運(yùn)用@Entity來界說實(shí)體:


接著創(chuàng)立數(shù)據(jù)庫類:


值得留意的是MyDatabase是一個籠統(tǒng)了,Room會在編譯期間供給它的一個完結(jié)類。

接下來需求界說DAO:


接著在MyDatabase中增加獲取上面這個DAO的辦法:


這兒的load辦法回來的是LiveData

現(xiàn)在我們能夠修正UserRepository了:


這兒盡管我們將UserRepository的直接數(shù)據(jù)來歷從Webservice改為本地數(shù)據(jù)庫,但我們卻不需求修正UserProfileViewModel或許UserProfileFragment。這就是籠統(tǒng)層帶來的優(yōu)點(diǎn)。這也給測驗(yàn)帶來了便利,由于你能夠供給一個虛偽的UserRepository來測驗(yàn)?zāi)愕腢serProfileViewModel。

現(xiàn)在,如果用戶從頭回到這個界面,他們會馬上看到數(shù)據(jù),由于我們現(xiàn)已將數(shù)據(jù)做了耐久化的保存。當(dāng)然如果有用例需求,我們也可不展現(xiàn)太老舊的耐久化數(shù)據(jù)。

在一些用例中,比方下拉改寫,如果正處于網(wǎng)絡(luò)懇求中,那UI需求通知用戶正處于網(wǎng)絡(luò)懇求中。一個好的實(shí)踐辦法就是將UI與數(shù)據(jù)別離,由于UI可能由于各種原因被更新。從UI的視點(diǎn)來說,懇求中的數(shù)據(jù)和本地數(shù)據(jù)相似,僅僅它還沒有被耐久化到數(shù)據(jù)庫中。

以下有兩種處理辦法:

將getUser的回來值中加入網(wǎng)絡(luò)狀況。
在Repository中供給一個能夠回來改寫狀況的辦法。如果你僅僅想在用戶經(jīng)過下拉改寫來通知用戶現(xiàn)在的網(wǎng)絡(luò)狀況的話,那這個辦法是比較合適的。
數(shù)據(jù)僅有來歷

在以上實(shí)例中,數(shù)據(jù)僅有來歷是數(shù)據(jù)庫,這樣做的優(yōu)點(diǎn)是用戶能夠依據(jù)安穩(wěn)的數(shù)據(jù)庫數(shù)據(jù)來更新頁面,而不需求處理許多的網(wǎng)絡(luò)懇求狀況。數(shù)據(jù)庫有數(shù)據(jù)則運(yùn)用,沒有數(shù)據(jù)則等候其更新。

測驗(yàn)

我們之前說到分層能夠個運(yùn)用供給杰出的測驗(yàn)才能,接下來就看看我們怎樣測驗(yàn)不同的模塊。

用戶界面與交互:這是僅有一個需求運(yùn)用到Android UI Instrumentation test的測驗(yàn)?zāi)K。測驗(yàn)UI的最好辦法就是運(yùn)用Espresso結(jié)構(gòu)。你能夠創(chuàng)立Fragment然后供給一個虛偽的ViewModel。由于Fragment只跟ViewModel交互,所以虛擬一個ViewModel就足夠了。

ViewModel:ViewModel能夠用JUnit test進(jìn)行測驗(yàn)。由于其不觸及界面與交互。而且你只需求虛擬UserRepository即可。

UserRepository:測驗(yàn)UserRepository相同運(yùn)用JUnit test。你能夠虛擬出Webservice和DAO。你能夠經(jīng)過運(yùn)用正確的網(wǎng)絡(luò)懇求來懇求數(shù)據(jù),讓后將數(shù)據(jù)經(jīng)過DAO寫入數(shù)據(jù)庫。如果數(shù)據(jù)庫中有相關(guān)數(shù)據(jù)則無需進(jìn)行網(wǎng)絡(luò)懇求。

UserDao:關(guān)于DAO的測驗(yàn),引薦運(yùn)用instrumentation進(jìn)行測驗(yàn)。由于此處無需UI,而且能夠運(yùn)用in-memory數(shù)據(jù)庫來確保測驗(yàn)的封閉性,不會影響到磁盤上的數(shù)據(jù)庫。

Webservice:堅(jiān)持測驗(yàn)的封閉性是適當(dāng)重要的,因而即便是你的Webservice測驗(yàn)也應(yīng)防止對后端進(jìn)行網(wǎng)絡(luò)呼叫。有許多第三方庫供給這方面的支撐。例如,MockWebServer是一個很棒的庫,能夠協(xié)助你為你的測驗(yàn)創(chuàng)立一個假的本地效勞器。

架構(gòu)圖




輔導(dǎo)準(zhǔn)則
編程是一個構(gòu)思范疇,構(gòu)建Android運(yùn)用程序也不破例。有多種辦法來處理問題,無論是在多個Activity或Fragment之間傳遞數(shù)據(jù),仍是檢索長途數(shù)據(jù)并將其在本地堅(jiān)持離線形式,或許是任何其他常見的場景。

盡管以下主張不是強(qiáng)制性的,但經(jīng)歷通知我們,遵從這些主張將使你的代碼庫從長遠(yuǎn)來看愈加強(qiáng)壯,可測驗(yàn)和可保護(hù)。

在AndroidManifest中界說的Activity,Service,Broadcast Receiver等,它們不是數(shù)據(jù)源。相反,他們僅僅用于協(xié)諧和展現(xiàn)數(shù)據(jù)。由于每個運(yùn)用程序組件的壽數(shù)適當(dāng)短,運(yùn)轉(zhuǎn)狀況取決于用戶與其設(shè)備的交互以及運(yùn)轉(zhuǎn)時的全體當(dāng)時運(yùn)轉(zhuǎn)狀況,所以不要將這些組件作為數(shù)據(jù)源。
你需求在運(yùn)用程序的各個模塊之間創(chuàng)立清晰界定的職責(zé)規(guī)模。例如,不要在不同的類或包之間傳遞用于加載網(wǎng)絡(luò)數(shù)據(jù)的代碼。相同,不要將數(shù)據(jù)緩存和數(shù)據(jù)綁定這兩個職責(zé)徹底不同的放在同一個類中。
每個模塊之間要竟可能少的彼此露出。不要抱有僥幸心理去揭露一個關(guān)于模塊的內(nèi)部完結(jié)細(xì)節(jié)的接口。你可能會在短期內(nèi)獲得到快捷,可是跟著代碼庫的開展,你將多付屢次技術(shù)性債款。
當(dāng)你界說模塊之間的交互時,請考慮怎樣使每個模塊阻隔。例如,具有用于從網(wǎng)絡(luò)中提取數(shù)據(jù)的界說杰出的API將使得更簡略測驗(yàn)在本地數(shù)據(jù)庫中耐久存在該數(shù)據(jù)的模塊。相反,如果將這兩個模塊的邏輯組合在一同,或許將整個代碼庫中的網(wǎng)絡(luò)代碼放在一同,那么測驗(yàn)就更難(如果不是不可能)。
你的運(yùn)用程序的中心是什么讓它獨(dú)立出來。不要花時刻重復(fù)輪子或一次又一次地編寫相同的樣板代碼。相反,將精力會集在使你的運(yùn)用程序絕無僅有的一起,讓Android架構(gòu)組件和其他引薦的庫來處理重復(fù)的樣板代碼。
堅(jiān)持盡可能多的相關(guān)聯(lián)的新鮮數(shù)據(jù),以便你的運(yùn)用程序在設(shè)備處于脫機(jī)形式時可用。盡管你能夠享用穩(wěn)定和高速銜接,但你的用戶可能不會。
你的Repository應(yīng)指定一個數(shù)據(jù)源作為實(shí)在的單一來歷。每逢你的運(yùn)用程序需求拜訪這些數(shù)據(jù)時,它應(yīng)該一直源于實(shí)在的單一來歷。
擴(kuò)展: 揭露網(wǎng)絡(luò)狀況
在上面的小結(jié)我們成心省掉了網(wǎng)絡(luò)過錯和加載狀況來確保比方的簡潔性。在這一小結(jié)我們演示一種運(yùn)用Resource類來封裝數(shù)據(jù)及其狀況。以此來揭露網(wǎng)絡(luò)狀況。

下面是簡略的Resource完結(jié):



認(rèn)為從網(wǎng)絡(luò)上抓取視頻的一起在UI上顯現(xiàn)數(shù)據(jù)庫的舊數(shù)據(jù)是很常見的用例,所以我們要創(chuàng)立一個能夠在多個當(dāng)?shù)刂貜?fù)運(yùn)用的協(xié)助類NetworkBoundResource。以下是NetworkBoundResource的決策樹:


NetworkBoundResource從調(diào)查數(shù)據(jù)庫開端,當(dāng)?shù)谝淮螐臄?shù)據(jù)庫加載完實(shí)體后,NetworkBoundResource會查看這個效果是否滿意用來展現(xiàn)的需求,如不滿意則需求從網(wǎng)上從頭獲取。當(dāng)然以上兩種狀況可能一起發(fā)作,你期望先將數(shù)據(jù)顯現(xiàn)在UI上的一起去網(wǎng)絡(luò)上懇求新數(shù)據(jù)。

如果網(wǎng)絡(luò)懇求效果,則將效果保存到數(shù)據(jù)庫,然后從頭從數(shù)據(jù)庫加載數(shù)據(jù),如果網(wǎng)絡(luò)懇求失利,則直接傳遞過錯信息。

留意:在上面的進(jìn)程中能夠看到當(dāng)將新數(shù)據(jù)保存到數(shù)據(jù)庫后,我們從頭從數(shù)據(jù)庫加載數(shù)據(jù)。盡管大部分狀況我們不用如此,由于數(shù)據(jù)庫會為我們傳遞此次更新。但另一方面,依靠數(shù)據(jù)庫內(nèi)部的更新機(jī)制并不是我們想要的如果更新的數(shù)據(jù)與舊數(shù)據(jù)共同,則數(shù)據(jù)谷不會做出更新提示。我們也不期望直接從網(wǎng)絡(luò)懇求中獲取數(shù)據(jù)直接用于UI,由于這樣違反了單一數(shù)據(jù)源的準(zhǔn)則。

下面是NetworkBoundResource類的公共api:


留意到上面界說了兩種泛型,ResultType和RequestType,由于從網(wǎng)絡(luò)懇求回來的數(shù)據(jù)類型可能會和數(shù)據(jù)庫回來的不共同。

別的留意到上面代碼中的ApiResponse這個類,他是將Retroft2.Call轉(zhuǎn)換成LiveData的一個簡略封裝。

下面是NetworkBoundResource余下部分的完結(jié):



接著我們就能夠在UserRepository中運(yùn)用NetworkBoundResource了。