您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Android LiveData的優(yōu)點(diǎn)有哪些”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Android LiveData的優(yōu)點(diǎn)有哪些”吧!
LiveData 是一個(gè)數(shù)據(jù)持有者類,它持有一個(gè)值并允許觀察該值。不同于普通的可觀察者,LiveData 遵守應(yīng)用程序組件的生命周期,以便 Observer 可以指定一個(gè)其應(yīng)該遵守的 Lifecycle。
如果 Observer 的 Lifecycle 處于 STARTED 或 RESUMED 狀態(tài),LiveData 會(huì)認(rèn)為 Observer 處于活動(dòng)狀態(tài)。
public class LocationLiveData extends LiveData<Location> { private LocationManager locationManager; private SimpleLocationListener listener = new SimpleLocationListener() { @Override public void onLocationChanged(Location location) { setValue(location); } }; public LocationLiveData(Context context) { locationManager = (LocationManager) context.getSystemService( Context.LOCATION_SERVICE); } @Override protected void onActive() { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener); } @Override protected void onInactive() { locationManager.removeUpdates(listener); } }
Location 監(jiān)聽(tīng)的實(shí)現(xiàn)有 3 個(gè)重要部分:
onActive():當(dāng) LiveData 有一個(gè)處于活動(dòng)狀態(tài)的觀察者時(shí)該方法被調(diào)用,這意味著需要開(kāi)始從設(shè)備觀察位置更新。
vonInactive():當(dāng) LiveData 沒(méi)有任何處于活動(dòng)狀態(tài)的觀察者時(shí)該方法被調(diào)用。由于沒(méi)有觀察者在監(jiān)聽(tīng),所以沒(méi)有理由保持與 LocationManager 的連接。這是非常重要的,因?yàn)楸3诌B接會(huì)顯著消耗電量并且沒(méi)有任何好處。
setValue():調(diào)用該方法更新 LiveData 實(shí)例的值,并將此變更通知給處于活動(dòng)狀態(tài)的觀察者。
可以像下面這樣使用新的 LocationLiveData:
public class MyFragment extends LifecycleFragment { public void onActivityCreated (Bundle savedInstanceState) { LiveData<Location> myLocationListener = ...; Util.checkUserStatus(result -> { if (result) { myLocationListener.addObserver(this, location -> { // update UI }); } }); } }
請(qǐng)注意,addObserver() 方法將 LifecycleOwner 作為***個(gè)參數(shù)傳遞。這樣做表示該觀察者應(yīng)該綁定到 Lifecycle,意思是:
如果 Lifecycle 不處于活動(dòng)狀態(tài)(STARTED 或 RESUMED),即使該值發(fā)生變化也不會(huì)調(diào)用觀察者。
如果 Lifecycle 被銷毀,那么自動(dòng)移除觀察者。
LiveData 是生命周期感知的事實(shí)給我們提供了一個(gè)新的可能:可以在多個(gè) activity,fragment 等之間共享它。為了保持實(shí)例簡(jiǎn)單,可以將其作為單例,如下所示:
public class LocationLiveData extends LiveData<Location> { private static LocationLiveData sInstance; private LocationManager locationManager; @MainThread public static LocationLiveData get(Context context) { if (sInstance == null) { sInstance = new LocationLiveData(context.getApplicationContext()); } return sInstance; } private SimpleLocationListener listener = new SimpleLocationListener() { @Override public void onLocationChanged(Location location) { setValue(location); } }; private LocationLiveData(Context context) { locationManager = (LocationManager) context.getSystemService( Context.LOCATION_SERVICE); } @Override protected void onActive() { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener); } @Override protected void onInactive() { locationManager.removeUpdates(listener); } }
現(xiàn)在 fragment 可以像下面這樣使用它:
public class MyFragment extends LifecycleFragment { public void onActivityCreated (Bundle savedInstanceState) { Util.checkUserStatus(result -> { if (result) { LocationLiveData.get(getActivity()).observe(this, location -> { // update UI }); } }); } }
可能會(huì)有多個(gè) fragment 和 activity 在觀察 MyLocationListener 實(shí)例,LiveData 可以規(guī)范的管理它們,以便只有當(dāng)它們中的任何一個(gè)可見(jiàn)(即處于活動(dòng)狀態(tài))時(shí)才連接到系統(tǒng)服務(wù)。
LiveData 有以下優(yōu)點(diǎn):
沒(méi)有內(nèi)存泄漏:因?yàn)?Observer 被綁定到它們自己的 Lifecycle 對(duì)象上,所以,當(dāng)它們的 Lifecycle 被銷毀時(shí),它們能自動(dòng)的被清理。
不會(huì)因?yàn)?activity 停止而崩潰:如果 Observer 的 Lifecycle 處于閑置狀態(tài)(例如:activity 在后臺(tái)時(shí)),它們不會(huì)收到變更事件。
始終保持?jǐn)?shù)據(jù)***:如果 Lifecycle 重新啟動(dòng)(例如:activity 從后臺(tái)返回到啟動(dòng)狀態(tài))將會(huì)收到***的位置數(shù)據(jù)(除非還沒(méi)有)。
正確處理配置更改:如果 activity 或 fragment 由于配置更改(如:設(shè)備旋轉(zhuǎn))重新創(chuàng)建,將會(huì)立即收到***的有效位置數(shù)據(jù)。
資源共享:可以只保留一個(gè) MyLocationListener 實(shí)例,只連接系統(tǒng)服務(wù)一次,并且能夠正確的支持應(yīng)用程序中的所有觀察者。
不再手動(dòng)管理生命周期:fragment 只是在需要的時(shí)候觀察數(shù)據(jù),不用擔(dān)心被停止或者在停止之后啟動(dòng)觀察。由于 fragment 在觀察數(shù)據(jù)時(shí)提供了其 Lifecycle,所以 LiveData 會(huì)自動(dòng)管理這一切。
LiveData 的轉(zhuǎn)換
有時(shí)候可能會(huì)需要在將 LiveData 發(fā)送到觀察者之前改變它的值,或者需要更具另一個(gè) LiveData 返回一個(gè)不同的 LiveData 實(shí)例。
Lifecycle 包提供了一個(gè) Transformations 類包含對(duì)這些操作的幫助方法。
,%20android.arch.core.util.Function
LiveData<User> userLiveData = ...; LiveData<String> userName = Transformations.map(userLiveData, user -> { user.name + " " + user.lastName });
,%20android.arch.core.util.Function
private LiveData<User> getUser(String id) { ...; } LiveData<String> userId = ...; LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );
使用這些轉(zhuǎn)換允許在整個(gè)調(diào)用鏈中攜帶觀察者的 Lifecycle 信息,以便只有在觀察者觀察到 LiveData 的返回時(shí)才運(yùn)算這些轉(zhuǎn)換。轉(zhuǎn)換的這種惰性運(yùn)算性質(zhì)允許隱式的傳遞生命周期相關(guān)行為,而不必添加顯式的調(diào)用或依賴。
每當(dāng)你認(rèn)為在 ViewModel 中需要一個(gè) Lifecycle 類時(shí),轉(zhuǎn)換可能是解決方案。
例如:假設(shè)有一個(gè) UI,用戶輸入一個(gè)地址然后會(huì)收到該地址的郵政編碼。該 UI 簡(jiǎn)單的 ViewModel 可能像這樣:
class MyViewModel extends ViewModel { private final PostalCodeRepository repository; public MyViewModel(PostalCodeRepository repository) { this.repository = repository; } private LiveData<String> getPostalCode(String address) { // DON'T DO THIS return repository.getPostCode(address); } }
如果是像這種實(shí)現(xiàn),UI 需要先從之前的 LiveData 注銷并且在每次調(diào)用 getPostalCode() 時(shí)重新注冊(cè)到新的實(shí)例。此外,如果 UI 被重新創(chuàng)建,它將會(huì)觸發(fā)新的 repository.getPostCode() 調(diào)用,而不是使用之前的調(diào)用結(jié)果。
不能使用那種方式,而應(yīng)該實(shí)現(xiàn)將地址輸入轉(zhuǎn)換為郵政編碼信息。
class MyViewModel extends ViewModel { private final PostalCodeRepository repository; private final MutableLiveData<String> addressInput = new MutableLiveData(); public final LiveData<String> postalCode = Transformations.switchMap(addressInput, (address) -> { return repository.getPostCode(address); }); public MyViewModel(PostalCodeRepository repository) { this.repository = repository } private void setInput(String address) { addressInput.setValue(address); } }
請(qǐng)注意,我們甚至使 postalCode 字段為 public final,因?yàn)樗肋h(yuǎn)不會(huì)改變。postalCode 被定義為 addressInput 的轉(zhuǎn)換,所以當(dāng) addressInput 改變時(shí),如果有處于活動(dòng)狀態(tài)的觀察者,repository.getPostCode() 將會(huì)被調(diào)用。如果在調(diào)用時(shí)沒(méi)有處于活動(dòng)狀態(tài)的觀察者,在添加觀察者之前不會(huì)進(jìn)行任何運(yùn)算。
該機(jī)制允許以較少的資源根據(jù)需要惰性運(yùn)算來(lái)創(chuàng)建 LiveData。ViewModel 可以輕松獲取到 LiveData 并在它們上面定義轉(zhuǎn)換規(guī)則。
創(chuàng)建新的轉(zhuǎn)換
在應(yīng)用程序中可能會(huì)用到十幾種不同的特定轉(zhuǎn)換,但是默認(rèn)是不提供的??梢允褂?MediatorLiveData 實(shí)現(xiàn)自己的轉(zhuǎn)換,MediatorLiveData 是為了用來(lái)正確的監(jiān)聽(tīng)其它 LiveData 實(shí)例并處理它們發(fā)出的事件而特別創(chuàng)建的。MediatorLiveData 需要特別注意正確的向源 LiveData 傳遞其處于活動(dòng)/閑置狀態(tài)。有關(guān)詳細(xì)信息,請(qǐng)參閱 Transformations 類。
到此,相信大家對(duì)“Android LiveData的優(yōu)點(diǎn)有哪些”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。