PS: The original article was published on wechat public account: Jzman-blog

LiveData is an observable data holder class that is lifecycle aware, unlike Observable. It is also part of the Android Jetpack component. This article will learn about LiveData from the following aspects:

  1. What is a LiveData
  2. The advantages of LiveData
  3. The use of LiveData
  4. Custom Livedata
  5. LiveData conversion

What is a LiveData

LiveData is an Observable data holder class. Unlike Observable, LiveData is aware of the lifecycle of activities, fragments, and services, ensuring that LiveData updates only component observers that are in the state of the Activity lifecycle.

If an application component observer is in the STARTED or RESUMED state, LiveData considers the component to be active and the component will receive data updates from LiveData, while other registered component observers will not receive any data updates.

#### Advantages of LiveData

  • Keep the UI consistent with the data: LiveData follows the Observer design pattern, notifying application components (observers) of changes in the life cycle and updating the UI when data changes occur.
  • Avoid memory leaks: This Observer is bound to a Lifecycle object and will be automatically cleaned up after the Lifecycle object destory.
  • Avoid crashes when an Activity is inactive: if an Observer is inactive, the Observer will not receive any LiveData events.
  • No manual lifecycle processing: UI components simply observe the relevant data, not stop or resume observation, and LiveData is automatically managed based on changes in the specific lifecycle.
  • Always keep the latest data: If the life cycle is inactive, the latest data will be received when the inactive state becomes active. For example, the latest data will be automatically received when the background is switched to the foreground.
  • Handle configuration changes correctly: If an Activity or Fragment is recreated due to a device configuration change, such as screen rotation, it will immediately rereceive the latest data.
  • Sharing service: The service can be connected or disconnected at any time according to the life cycle state of Livecycle with the help of the observation capability of LiveData data.

The use of LiveData

Define the LiveData in a specific ViewModel class, and then observe the change of the LiveData in the corresponding Activity or Fragment. The use of LiveData allows us to save the data stored in the LiveData object in the ViewModel instead of the Activity or Fragment, reducing the workload of the Activity and Fragment. Activities and fragments are only responsible for interface management and display, not for saving data, and the data is not affected when the configuration changes.

Summary of LiceData usage:

  1. Create a concrete LiveData instance in the ViewModel to store the data as follows:
public class MViewModel extends ViewModel {
    private MutableLiveData<String> data;
    public LiveData<String> getData(a){
        if (data == null){
            data = new MutableLiveData<>();
            data.postValue(DataUtil.getData());
        }
        returndata; }}Copy the code
  1. Use the observe or observeForever method of the LiveData object to add the corresponding Activity or Fragment to the observer of the LiveData object, as follows:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
    MViewModel mViewModel = ViewModelProviders.of(this).get(MViewModel.class);
    mViewModel.getData().observe(this.new Observer<String>() {
        @Override
        public void onChanged(String msg) { binding.setData(msg); }}); }Copy the code
  1. Update the data using setValue or postValue in LiveData, and then retrieve the updated data in the observer (Activity or Fragment), as follows:
public void setData(String data) {
    mData.setValue(data);
}
Copy the code

So how do you create an observer without LifecycleOwner? You can use the observeForever method of the LiveData object to add a class without a LifecycleOwner to the list of observers, as follows:

public class NoLifecycleOwner {
    public void print(NViewModel viewModel, final TextView tvData){
        // Use the observeForever object to create an observer without LifecycleOwner
        viewModel.getData().observeForever(new Observer<String>() {
            @Override
            public void onChanged(String s) {
                tvData.setText("I am an observer without LifecycleOwner :"+s); }}); }}Copy the code

However, using observeForever to get the Observer object will always be active, so we need to manually call removeObserver(Observer) to remove the Observer.

Custom Livedata

You can use the Life cycle awareness capability of the LiveData object to provide services externally, and you can easily control the opening and closing of services, as follows:

/** * Customizable LiveData * Powered by jzman. * Created on 2018/12/170017. */
public class CustomLiveData extends LiveData<String{

    @Override
    protected void onActive(a) {
        // This method is called by an active observer
        // Start the service...
    }

    @Override
    protected void onInactive(a) {
        // There are no active observers calling this method
        // End the service...}}Copy the code

LiveData conversion

Lifecycle provides a tool class that transforms the data types of the LiveData before it is returned to the viewer. MapViewModel = MapViewModel = MapViewModel = MapViewModel = MapViewModel = MapViewModel = MapViewModel = MapViewModel = MapViewModel = MapViewModel

/** * LiveData conversion * Powered by jzman. * Created on 2018/12/170017. */
public class MapViewModel extends ViewModel {
    private MutableLiveData<Integer> mPrice = new MutableLiveData<>();

    //Map
    private LiveData<String> mMapPrice = Transformations.map(mPrice, new Function<Integer, String>() {
        @Override
        public String apply(Integer input) {
            / / return a String
            returnUtil.getNumberCapital(input); }});//SwitchMap
    private LiveData<String> mSwitchMapPrice = Transformations.switchMap(mPrice, new Function<Integer, LiveData<String>>() {
        @Override
        public LiveData<String> apply(Integer input) {
            / / return LiveData
            MutableLiveData<String> data = new MutableLiveData<>();
            data.postValue(Util.getNumberCapital(input));
            returndata; }});public void setPrice(int price) {
        mPrice.setValue(price);
    }

    public LiveData<String> getPrice(a) {
        //Map
        return mMapPrice;
        //SwitchMap
// return mSwitchMapPrice;}}Copy the code

Then, watch the data change in the Activity as follows:

public class MapActivity extends AppCompatActivity {
    private MapViewModel mapViewModel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final ActivityMapBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_map);
        mapViewModel = new MapViewModel();
        mapViewModel.getPrice().observe(this.new Observer<String>() {
            @Override
            public void onChanged(String s) {
                // Convert numbers to Chinese uppercasebinding.tvData.setText(s); }}); }public void btnSetPrice1(View view) {
        mapViewModel.setPrice(1);
    }

    public void btnSetPrice2(View view) {
        mapViewModel.setPrice(2); }}Copy the code

The only difference between map and switchMap is that Map converts LiveData to specific types, such as String in the code above, whereas switchMap is LiveData. GetNumberCapital (); getNumberCapital ();

jzman-blog

The Map and switchMap methods are internally converted by MediatorLiveData. You can use MediatorLiveData to perform more map and switch conversions.