Android 架构组件 - LiveData

https://www.jianshu.com/p/87aa6464412b

https://developer.android.google.cn/topic/libraries/architecture/livedata#the_advantages_of_using_livedata

consolidate(统一;把…合成一体,合并;巩固,加强;合计金额)

propagates(传播,繁衍)

respects 敬意;敬意,问候;考虑( respect的名词复数 );关联,尊敬;尊重( respect的第三人称单数 );关心;慎重对待

the observer pattern 观察者模式

 as opposed to(与⋯⋯相对,而不是)

bloated (发胀的;浮肿的;傲慢的)

decouple(使分离,解耦)

 a second time表示又一次、再一次的意思

Applies(实现) 

downstream(下游)

unwraps 解开包装

LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects(涉及) the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.

Note: To import LiveData components into your Android project, see Adding Components to your Project.

LiveData considers an observer, which is represented by the Observer class, to be in an active state if its lifecycle is in the STARTED or RESUMED state. LiveData only notifies active observers about updates. Inactive observers registered to watch LiveData objects aren't notified about changes.

You can register an observer paired with an object that implements the LifecycleOwner interface. This relationship allows the observer to be removed when the state of the corresponding Lifecycle object changes to DESTROYED. This is especially useful for activities and fragments because they can safely observe LiveData objects and not worry about leaks—activities and fragments are instantly unsubscribed when their lifecycles are destroyed.

For more information about how to use LiveData, see Work with LiveData objects.

The advantages of using LiveData

Using LiveData provides the following advantages:

Ensures your UI matches your data state

LiveData follows the observer pattern(观察者模式). LiveData notifies Observer objects when the lifecycle state changes. You can consolidate(合并)your code to update the UI in these Observer objects. Instead of updating the UI every time the app data changes, your observer can update the UI every time there's a change.

No memory leaks

Observers are bound to Lifecycle objects and clean up after themselves when their associated lifecycle is destroyed.

No crashes due to stopped activities

If the observer's lifecycle is inactive, such as in the case of an activity in the back stack, then it doesn’t receive any LiveData events.

No more manual lifecycle handling

UI components just observe relevant data and don’t stop or resume observation. LiveData automatically manages all of this since it’s aware of the relevant lifecycle status changes while observing.

Always up to date data

If a lifecycle becomes inactive, it receives the latest data upon becoming active again. For example, an activity that was in the background receives the latest data right after it returns to the foreground.

Proper configuration changes

If an activity or fragment is recreated due to a configuration change, like device rotation, it immediately receives the latest available data.

Sharing resources

You can extend a LiveData object using the singleton pattern to wrap system services so that they can be shared in your app. The LiveData object connects to the system service once, and then any observer that needs the resource can just watch the LiveData object. For more information, see Extend LiveData.

Work with LiveData objects

Follow these steps to work with LiveData objects:

Create an instance of LiveData to hold a certain type of data. This is usually done within your ViewModel class.

Create an Observer object that defines the onChanged() method, which controls what happens when the LiveData object's held data changes. You usually create an Observer object in a UI controller, such as an activity or fragment.

Attach the Observer object to the LiveData object using the observe() method. The observe() method takes a LifecycleOwner object. This subscribes the Observer object to the LiveData object so that it is notified of changes. You usually attach the Observer object in a UI controller, such as an activity or fragment.

Note: You can register an observer without an associated LifecycleOwner object using theobserveForever(Observer) method. In this case, the observer is considered to be always active and is therefore always notified about modifications. You can remove these observers calling the removeObserver(Observer)method.


LiveData OverviewPart of Android Jetpack.

LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.

Note: To import LiveData components into your Android project, see Adding Components to your Project.

LiveData considers an observer, which is represented by the Observer class, to be in an active state if its lifecycle is in the STARTED or RESUMED state. LiveData only notifies active observers about updates. Inactive observers registered to watch LiveData objects aren't notified about changes.

You can register an observer paired with an object that implements the LifecycleOwner interface. This relationship allows the observer to be removed when the state of the corresponding Lifecycle object changes to DESTROYED. This is especially useful for activities and fragments because they can safely observe LiveData objects and not worry about leaks—activities and fragments are instantly unsubscribed when their lifecycles are destroyed.

For more information about how to use LiveData, see Work with LiveData objects.

The advantages of using LiveData

Using LiveData provides the following advantages:

Ensures your UI matches your data state

LiveData follows the observer pattern. LiveData notifies Observer objects when the lifecycle state changes. You can consolidate your code to update the UI in these Observer objects. Instead of updating the UI every time the app data changes, your observer can update the UI every time there's a change.

No memory leaks

Observers are bound to Lifecycle objects and clean up after themselves when their associated lifecycle is destroyed.

No crashes due to stopped activities

If the observer's lifecycle is inactive, such as in the case of an activity in the back stack, then it doesn’t receive any LiveData events.

No more manual lifecycle handling

UI components just observe relevant data and don’t stop or resume observation. LiveData automatically manages all of this since it’s aware of the relevant lifecycle status changes while observing.

Always up to date data

If a lifecycle becomes inactive, it receives the latest data upon becoming active again. For example, an activity that was in the background receives the latest data right after it returns to the foreground.

Proper configuration changes

If an activity or fragment is recreated due to a configuration change, like device rotation, it immediately receives the latest available data.

Sharing resources

You can extend a LiveData object using the singleton pattern to wrap system services so that they can be shared in your app. The LiveData object connects to the system service once, and then any observer that needs the resource can just watch the LiveData object. For more information, see Extend LiveData.

Work with LiveData objects

Follow these steps to work with LiveData objects:

Create an instance of LiveData to hold a certain type of data. This is usually done within your ViewModel class.

Create an Observer object that defines the onChanged() method, which controls what happens when the LiveData object's held data changes. You usually create an Observer object in a UI controller, such as an activity or fragment.

Attach the Observer object to the LiveData object using the observe() method. The observe() method takes a LifecycleOwner object. This subscribes the Observer object to the LiveData object so that it is notified of changes. You usually attach the Observer object in a UI controller, such as an activity or fragment.

Note: You can register an observer without an associated LifecycleOwner object using theobserveForever(Observer) method. In this case, the observer is considered to be always active and is therefore always notified about modifications. You can remove these observers calling the removeObserver(Observer)method.

When you update the value stored in the LiveData object, it triggers all registered observers as long as the attached LifecycleOwner is in the active state.

LiveData allows UI controller observers to subscribe to updates. When the data held by the LiveData object changes, the UI automatically updates in response.

Create LiveData objects

LiveData is a wrapper that can be used with any data, including objects that implement Collections, such as List. ALiveData object is usually stored within a ViewModel object and is accessed via a getter method, as demonstrated in the following example:

KOTLIN

JAVA

public class NameViewModel extends ViewModel {

// Create a LiveData with a Stringprivate MutableLiveData<String> mCurrentName;

public MutableLiveData<String> getCurrentName() {if (mCurrentName == null) {

mCurrentName

= new MutableLiveData<String>();}return mCurrentName;}

// Rest of the ViewModel...}

Initially, the data in a LiveData object is not set.

Note: Make sure to store LiveData objects that update the UI in ViewModel objects, as opposed to(与⋯⋯相对,而不是) an activity or fragment, for the following reasons:

To avoid bloated (发胀的;浮肿的;傲慢的)activities and fragments. Now these UI controllers are responsible for displaying data but not holding data state.

To decouple(使分离) LiveData instances from specific activity or fragment instances and allow LiveData objects to survive configuration changes.

You can read more about the benefits and usage of the ViewModel class in the ViewModel guide.

Observe LiveData objects

In most cases, an app component’s onCreate() method is the right place to begin observing a LiveData object for the following reasons:

To ensure the system doesn’t make redundant calls from an activity or fragment’s onResume() method.

To ensure that the activity or fragment has data that it can display as soon as it becomes active. As soon as an app component is in the STARTED state, it receives the most recent value from the LiveData objects it’s observing. This only occurs if the LiveData object to be observed has been set.

Generally, LiveData delivers updates only when data changes, and only to active observers. An exception to this behavior is that observers also receive an update when they change from an inactive to an active state. Furthermore, if the observer changes from inactive to active a second time表示又一次、再一次的意思, it only receives an update if the value has changed since the last time it became active.

The following sample code illustrates how to start observing a LiveData object:

public class NameActivity extends AppCompatActivity {

private NameViewModel mModel;

@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);

// Other code to setup the activity...

// Get the ViewModel.

mModel

= ViewModelProviders.of(this).get(NameViewModel.class);

// Create the observer which updates the UI.final Observer<String> nameObserver = new Observer<String>() {@Overridepublic void onChanged(@Nullable final String newName) {// Update the UI, in this case, a TextView.

mNameTextView

.setText(newName);}};

// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.

mModel

.getCurrentName().observe(this, nameObserver);}}

After observe() is called with nameObserver passed as parameter, onChanged() is immediately invoked providing the most recent value stored in mCurrentName. If the LiveData object hasn't set a value in mCurrentName, onChanged() is not called.

Update LiveData objects

LiveData has no publicly available methods to update the stored data. The MutableLiveData class exposes thesetValue(T) and postValue(T) methods publicly and you must use these if you need to edit the value stored in a LiveData object. Usually MutableLiveData is used in the ViewModel and then the ViewModel only exposes immutable LiveData objects to the observers.

After you have set up the observer relationship, you can then update the value of the LiveData object, as illustrated by the following example, which triggers all observers when the user taps a button:

KOTLIN

JAVA

mButton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {String anotherName = "John Doe";

mModel

.getCurrentName().setValue(anotherName);}});

Calling setValue(T) in the example results in the observers calling their onChanged() methods with the value John Doe. The example shows a button press, but setValue() or postValue() could be called to update mName for a variety of reasons, including in response to a network request or a database load completing; in all cases, the call to setValue() or postValue() triggers observers and updates the UI.

Note: You must call the setValue(T) method to update the LiveData object from the main thread. If the code is executed in a worker thread, you can use the postValue(T) method instead to update the LiveData object.

Use LiveData with Room

The Room persistence library supports observable queries, which return LiveData objects. Observable queries are written as part of a Database Access Object (DAO).

Room generates all the necessary code to update the LiveData object when a database is updated. The generated code runs the query asynchronously on a background thread when needed. This pattern is useful for keeping the data displayed in a UI in sync with the data stored in a database. You can read more about Room and DAOs in the Room persistent library guide.

Extend LiveData

LiveData considers an observer to be in an active state if the observer's lifecycle is in either the STARTED or RESUMEDstates The following sample code illustrates how to extend the LiveData class:

KOTLIN

JAVA

public class StockLiveData extends LiveData<BigDecimal> {private StockManager mStockManager;

private SimplePriceListener mListener = new SimplePriceListener() {@Overridepublic void onPriceChanged(BigDecimal price) {

setValue

(price);}};

public StockLiveData(String symbol) {

mStockManager

= new StockManager(symbol);}

@Overrideprotected void onActive() {

mStockManager

.requestPriceUpdates(mListener);}

@Overrideprotected void onInactive() {

mStockManager

.removeUpdates(mListener);}}

The implementation of the price listener in this example includes the following important methods:

The onActive() method is called when the LiveData object has an active observer. This means you need to start observing the stock price updates from this method.

The onInactive() method is called when the LiveData object doesn't have any active observers. Since no observers are listening, there is no reason to stay connected to the StockManager service.

The setValue(T) method updates the value of the LiveData instance and notifies any active observers about the change.

You can use the StockLiveData class as follows:

KOTLIN

JAVA

public class MyFragment extends Fragment {@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);LiveData<BigDecimal> myPriceListener = ...;

myPriceListener

.observe(this, price -> {// Update the UI.});}}

The observe() method passes the fragment, which is an instance of LifecycleOwner, as the first argument. Doing so denotes that this observer is bound to the Lifecycle object associated with the owner, meaning:

If the Lifecycle object is not in an active state, then the observer isn't called even if the value changes.

After the Lifecycle object is destroyed, the observer is automatically removed.

The fact that LiveData objects are lifecycle-aware means that you can share them between multiple activities, fragments, and services. To keep the example simple, you can implement the LiveData class as a singleton as follows:

KOTLIN

JAVA

public class StockLiveData extends LiveData<BigDecimal> {private static StockLiveData sInstance;private StockManager mStockManager;

private SimplePriceListener mListener = new SimplePriceListener() {@Overridepublic void onPriceChanged(BigDecimal price) {

setValue

(price);}};

@MainThreadpublic static StockLiveData get(String symbol) {if (sInstance == null) {

sInstance

= new StockLiveData(symbol);}return sInstance;}

private StockLiveData(String symbol) {

mStockManager

= new StockManager(symbol);}

@Overrideprotected void onActive() {

mStockManager

.requestPriceUpdates(mListener);}

@Overrideprotected void onInactive() {

mStockManager

.removeUpdates(mListener);}}

And you can use it in the fragment as follows:

KOTLIN

JAVA

public class MyFragment extends Fragment {@Overridepublic void onActivityCreated(Bundle savedInstanceState) {StockLiveData.get(symbol).observe(this, price -> {// Update the UI.});}}

Multiple fragments and activities can observe the MyPriceListener instance. LiveData only connects to the system service if one or more of them is visible and active.

Transform LiveData

You may want to make changes to the value stored in a LiveData object before dispatching it to the observers, or you may need to return a different LiveData instance based on the value of another one. The Lifecycle package provides the Transformations class which includes helper methods that support these scenarios.

Transformations.map()

Applies(实现) a function on the value stored in the LiveData object, and propagates(传播) the result downstream(下游).

KOTLIN

JAVA

LiveData<User> userLiveData = ...;LiveData<String> userName = Transformations.map(userLiveData, user -> {

user

.name + " " + user.lastName

});

Transformations.switchMap()

Similar to map(), applies a function to the value stored in the LiveData object and unwraps 解开包装 and dispatches the result downstream. The function passed to switchMap() must return a LiveData object, as illustrated by the following example:

KOTLIN

JAVA

private LiveData<User> getUser(String id) {...;}

LiveData<String> userId = ...;LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );

You can use transformation methods to carry information across the observer's lifecycle. The transformations aren't calculated unless an observer is watching the returned LiveData object. Because the transformations are calculated lazily, lifecycle-related behavior is implicitly 隐含地passed down without requiring additional explicit calls or dependencies.


If you think you need a Lifecycle object inside a ViewModel object, a transformation is probably a better solution. For example, assume that you have a UI component that accepts an address and returns the postal code for that address. You can implement the naive ViewModel for this component as illustrated by the following sample code:

KOTLIN

JAVA

class MyViewModel extends ViewModel {private final PostalCodeRepository repository;public MyViewModel(PostalCodeRepository repository) {this.repository = repository;}

private LiveData<String> getPostalCode(String address) {// DON'T DO THISreturn repository.getPostCode(address);}}

The UI component then needs to unregister from the previous LiveData object and register to the new instance each time it calls getPostalCode(). In addition, if the UI component is recreated, it triggers another call to therepository.getPostCode() method instead of using the previous call’s result.

Instead, you can implement the postal code lookup as a transformation of the address input, as shown in the following example:

KOTLIN

JAVA

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);}}

In this case, the postalCode field is defined as a transformation of the addressInput. As long as your app has an active observer associated with the postalCode field, the field's value is recalculated and retrieved wheneveraddressInput changes.

This mechanism allows lower levels of the app to create LiveData objects that are lazily calculated on demand. A ViewModel object can easily obtain references to LiveData objects and then define transformation rules on top of them.

Create new transformations

There are a dozen different specific transformation that may be useful in your app, but they aren’t provided by default. To implement your own transformation you can you use the MediatorLiveData class, which listens to other LiveDataobjects and processes events emitted by them. MediatorLiveData correctly propagates its state to the source LiveData object. To learn more about this pattern, see the reference documentation of the Transformations class.

Merge multiple LiveData sources

MediatorLiveData is a subclass of LiveData that allows you to merge multiple LiveData sources. Observers of MediatorLiveData objects are then triggered whenever any of the original LiveData source objects change.

For example, if you have a LiveData object in your UI that can be updated from a local database or a network, then you can add the following sources to the MediatorLiveData object:

A LiveData object associated with the data stored in the database.

A LiveData object associated with the data accessed from the network.

Your activity only needs to observe the MediatorLiveData object to receive updates from both sources. For a detailed example, see the Addendum: exposing network status section of the Guide to App Architecture.

Additional resources

LiveData is used in the Sunflower demo app.

Also see the Architecture Components BasicSample .

For additional information on using LiveData with Snackbar messages, navigation events, and other events, read this post.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,825评论 4 377
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,887评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,425评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,801评论 0 224
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,252评论 3 299
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,089评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,216评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 31,005评论 0 215
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,747评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,883评论 2 255
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,354评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,694评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,406评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,222评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,242评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,017评论 2 281