Live data

AndroidX provides classes to implement the MVVM pattern.

LiveData is an observable data holder class. Unlike a regular observable, it takes into account the lifecycle of other app components, such as activities, fragments, or services.

The ViewModel is a class that is responsible for preparing and managing the data for an Activity or a Fragment. It also handles the communication of the Activity/Fragment with the rest of the application.

A LiveData object is usually stored within a ViewModel object.

class NameViewModel : ViewModel() {

    // Create a LiveData with a String
    val currentName: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

    // ...
}
Add dependencies for viewmodel, lifecycle and live data

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

class NameActivity : AppCompatActivity() {

    // Use the 'by viewModels()' Kotlin property delegate
    // from the activity-ktx artifact
    private val model: NameViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ...
        
        // Create the observer which updates the UI.
        val nameObserver = Observer<String> { newName ->
            // Update the UI, in this case, a TextView.
            nameTextView.text = newName
        }

        // Observe the LiveData, passing in this activity 
        // as the LifecycleOwner and the observer.
        model.currentName.observe(this, nameObserver)
    }
}
public class NameActivity extends AppCompatActivity {

    private NameViewModel model;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ... 
        
        // Get the ViewModel
        model = new ViewModelProvider(this).get(NameViewModel.class);

        // Create the observer which updates the UI.
        final Observer<String> nameObserver = new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String newName) {
                nameTextView.setText(newName); // update the UI, in this case, a TextView.
            }
        };

        // Observe the LiveData, passing in this activity 
        // as the LifecycleOwner and the observer.
        model.getCurrentName().observe(this, nameObserver);
    }
}

Fragments can get the activity viewmodel via activityViewModels() method.

Share viewmodel with fragments

A fragment can define its own view model and share it with a child fragment.

Fragment viewmodel

Transformations

The Transformations allows to add transformation to the LiveData. The transformations are calculated lazily, and will run only when the returned LiveData is observed. Lifecycle behavior is propagated from the input source LiveData to the returned one.

val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<String> = Transformations.map(userLiveData) {
    user -> "${user.name} ${user.lastName}"
}
static method description
distinctUntilChanged(lvSource) Creates a new LiveData object that does not emit a value until the source LiveData value has been changed.
map(ldSource, func) Returns a LiveData mapped from the input source LiveData by applying func to each value set on source.
switchMap(ldSource, ldFunc) Returns a LiveData mapped from the input source LiveData by applying ldFunc to each value set on source.

custom LiveData

Custom LiveData
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
    private val stockManager = StockManager(symbol)

    private val listener = { price: BigDecimal ->
        value = price
    }

    override fun onActive() {
        stockManager.requestPriceUpdates(listener)
    }

    override fun onInactive() {
        stockManager.removeUpdates(listener)
    }
}
public class StockLiveData extends LiveData<BigDecimal> {
    private StockManager stockManager;

    private SimplePriceListener listener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) {
            setValue(price);
        }
    };

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

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

    @Override
    protected void onInactive() {
        stockManager.removeUpdates(listener);
    }
}
  • onActive() method is called when the LiveData object has an active observer
  • onInactive() method is called when the LiveData object doesn't have any active observers
  • setValue() method updates the value of the LiveData instance and notifies any active observers about the change

Also see examples with coroutines.

LiveData vs ...

It is not recommended to use LiveData beyond the UI. Use RxJava library or listeners.

If you need many transformation operators, use RxJava.

If you have one-shot operation, you can use coroutines. For example, to fetch some data.