This article was first published on the wechat public account “Houchangcun Mannong”

preface

RxJava has been very popular around 2017, and I covered the use and principles of RxJava in the first installment of the Android Advanced Trilogy, Advanced Light of Android. LiveData from Google is similar to RxJava in that it is observer based and you can think of LiveData as lightweight RxJava. At the beginning, LiveData was not regarded as promising, but with Google’s vigorous promotion, LiveData gradually came into everyone’s view. In general, LiveData is rarely used on its own, but more often in conjunction with other components of Android Jetpack, such as ViewModel. This article will introduce the use of LiveData.

1. What is LiveData

LiveData is, as its name suggests, an observable data holder. Unlike a normal Observable, LiveData is lifecycle aware, which means it can properly handle life cycles in activities, fragments, and services.

1. Basic usage of LiveData

LiveData is an abstract class, its simplest implementation class is MutableLiveData, here is the simplest example.

public class MainActivity extends AppCompatActivity {
   private static final String TAG="MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MutableLiveData<String> mutableLiveData  = new MutableLiveData<>();
        mutableLiveData.observe(this.new Observer<String>() {/ / 1
            @Override
            public void onChanged(@Nullable final String s) {
                Log.d(TAG, "onChanged:"+s); }}); mutableLiveData.postValue("Android Advanced Trilogy");/ / 2}}Copy the code

The observe method in comment 1 has two arguments LifecycleOwner and Observer

. The first argument is MainActivity itself, and the second argument creates a new Observer

, which is called back in the onChanged method. The postValue method at the comment updates the data in the main thread, so you get the printed result. D/MainActivity: onChanged:Android Advanced trilogy

In most cases, LiveData’s observe method will be placed in the onCreate method, and if it is placed in the onResume method, it will be called more than once. In addition to MutableLiveData’s postValue method, you can also use the setValue method. The difference is that the setValue method must be used on the main thread, whereas the postValue method can be used when updating LiveData in a worker thread.

2. Change the data in LiveData

If we want before distributed to observer LiveData object to store the value of the changes, you can use Transformations. The map () and Transformations. SwitchMap (), with simple examples to explain them.

2.1 Transformations. The map ()

If you want to make changes to the values stored in LiveData objects before they are distributed to observers, you can use Mineral.map ().

public class MainActivity extends AppCompatActivity {
   private static final String TAG="MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MutableLiveData<String> mutableLiveData  = new MutableLiveData<>();
        mutableLiveData.observe(this.new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String s) {
                Log.d(TAG, "onChanged1:"+s); }}); LiveData transformedLiveData =Transformations.map(mutableLiveData,new Function<String, Object>() {
            @Override
            public Object apply(String name) {
               return name + "+Android Advanced Decryption"; }}); transformedLiveData.observe(this.new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d(TAG, "onChanged2:"+o.toString()); }}); mutableLiveData.postValue("Android Advanced Light"); }}Copy the code

Mineral.map () adds the string +Android advanced decryption to mutableLiveData. The output is: D/MainActivity: onChanged1:Android Advanced Light D/MainActivity: onChanged2:Android Advanced light +Android Advanced decryption

2.2 Transformations. SwitchMap ()

If you want one manual control to monitor data changes, and can switch to monitor at any time according to need, then you can use Transformations. SwitchMap (), and Transformations. It use way similar to map (), Only switchMap() must return a LiveData object.

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    MutableLiveData<String> mutableLiveData1;
    MutableLiveData<String> mutableLiveData2;
    MutableLiveData<Boolean> liveDataSwitch;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mutableLiveData1 = new MutableLiveData<>();
        mutableLiveData2 = new MutableLiveData<>();
        liveDataSwitch = new MutableLiveData<Boolean>();/ / 1

        LiveData transformedLiveData= Transformations.switchMap(liveDataSwitch, new Function<Boolean, LiveData<String>>() {
            @Override
            public LiveData<String> apply(Boolean input) {
                if (input) {
                    return mutableLiveData1;
                } else {
                    returnmutableLiveData2; }}}); transformedLiveData.observe(this.new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String s) {
                Log.d(TAG, "onChanged:"+ s); }}); liveDataSwitch.postValue(false);/ / 2
        mutableLiveData1.postValue("Android Advanced Light");
        mutableLiveData2.postValue("Advanced Decryption for Android"); }}Copy the code

Create a new MutableLiveData

() at comment 1 to control the switch and assign it to liveDataSwitch. Return mutableLiveData1 when liveDataSwitch is true. Otherwise, return mutableLiveData2. In comment 2, update liveDataSwitch to false, so that the output result is “Android advanced decryption “, so that the purpose of switching listening is achieved.

Merge multiple LiveData sources

MediatorLiveData inherits from mutableLiveData, which can aggregate multiple LiveData sources and enable a component to monitor changes of multiple LiveData data.

public class MainActivity extends AppCompatActivity {
   private static final String TAG="MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MutableLiveData<String> mutableLiveData1  = new MutableLiveData<>();
        MutableLiveData<String> mutableLiveData2  = new MutableLiveData<>();
        MediatorLiveData liveDataMerger = new MediatorLiveData<String>();
        liveDataMerger.addSource(mutableLiveData1, new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d(TAG, "onChanged1:"+o.toString()); }}); liveDataMerger.addSource(mutableLiveData2,new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d(TAG, "onChanged2:"+o.toString()); }}); liveDataMerger.observe(this.new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d(TAG, "onChanged:"+o.toString()); }}); mutableLiveData1.postValue("Android Advanced Light"); }}Copy the code

For a more intuitive example, LiveData and MediatorLiveData are placed in the same Activity. MediatorLiveData merges the two MutableLiveData together using the addSource of MediatorLiveData so that MediatorLiveData can sense when any MutableLiveData data changes.

The printed result is: D/MainActivity: onChanged1:Android Advanced Light

4 Expand LiveData objects

LiveData treats the observer as Active if the observer’s life cycle is STARTED or RESUMED. The example on the official website on how to extend LiveData is very succinct, as shown below.

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

    private SimplePriceListener listener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) { setValue(price); }};@MainThread
    public static StockLiveData get(String symbol) {
        if (sInstance == null) {
            sInstance = new StockLiveData(symbol);
        }
        return sInstance;
    }

    private StockLiveData(String symbol) {
        stockManager = new StockManager(symbol);
    }

    @Override
    protected void onActive(a) {
        stockManager.requestPriceUpdates(listener);
    }

    @Override
    protected void onInactive(a) { stockManager.removeUpdates(listener); }}Copy the code

The code above is an example of observing stock movements and extends LiveData to implement its two empty methods onActive and onInactive. The onActive method is called when the number of observers in the Active state changes from 0 to 1. Generally speaking, the onActive method is called when the LiveData object has an Active observer, and the onActive method should start observing the update of the stock price. The onInactive method is called when the LiveData object does not have any observers in the Active state. In this method, the connection to the StockManager service is disconnected.

Use StockLiveData in the Fragment, as shown below.

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

conclusion

This article mainly introduces what LiveData is and how to use LiveData. The combination of LiveData and ViewModel and the principle of LiveData are not introduced here, which will be introduced in later articles.

For more information, check out my independent blog’s body of knowledge: liuwangshu.cn/system/


Here not only share big front end, Android, Java and other technologies, but also programmer growth class articles.