Live Data. Difference between livedata and mutable live data. Mediator Live Data. Live Data Encapsulation
Before introducing live data , we need to manually handle the updates in the UI. We were using traditional approaches like interfaces, events buses to update the UI. These traditional approaches having problem like manual handling of lifecycle, memory leaks, and crashes.
Live Data
It is wrapper which can be used with any data such as data and objects that implements collections like list. A Live Data usually declared and used inside a view model class. Live Data can be used to observe the change of a particular data and update the UI based on that. Due to life cycle aware property we don't need to bother about components life cycle. i.e. it will send the update only when the component (activity/fragment) is in active state. If the component is not active now and in future when it is active, live data will send the updated data to the component
Example of live data.
private val _result= MutableLiveData<String>() //in view model class
//in Activity/Fragment
wrapperViewModel.result.observe(this, Observer {
})
Features of Live Data
- Life Cycle Aware
- Observable
- Data holder
If we want to communicate between two components , its quite difficult because we need to consider its life cycles and life spans. Live Data is based on the observable pattern which makes the communication between the view and view model easy. Live Data notifies Observer objects when the underlying data changes. Therefore you don't need to update the ui every time when the data changes, Observable will do it for you
Advantages of Live Data
- It keeps UI updated
- It will destroy automatically when the life cycle owner is destroyed
- Ensures crashes
- Can be shared with multiple resources
Types of Live Data
- LiveData
- MutableLiveData
- MediatorLive Data
LiveData liveData= MutableLiveData<String>()
val mediatorLiveData=MediatorLiveData<String>()
- If you need lot of operations or streams then never use live data, you can go for RX
- If your operation is not about ui or lifecycle, then you can use callback interface
- If you have short operation chaining , then you can use coroutine
When you establish that transformation , lifecycle is automatically carried over for you , if you run a transformation of couple of live data, when you subscribe it the lifecycle is automatically propagated to inner live data
Transformation- map()
It is a one to one static transformation.
LiveData<Y> map (LiveData<X> source, Function<X, Y> func)
def lifecycle_version = '2.5.1'
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="200dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<Button
android:layout_marginTop="50dp"
app:layout_constraintTop_toBottomOf="@+id/textValue"
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Increment"
app:layout_constraintRight_toLeftOf="@+id/textValue"
/>
<Button
android:layout_marginTop="50dp"
app:layout_constraintTop_toBottomOf="@+id/textValue"
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Decrement"
app:layout_constraintLeft_toRightOf="@+id/textValue"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity
package com.learning.livedataexample
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.learning.livedataexample.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: ActivityViewModel
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
viewModel= ViewModelProvider(this)[ActivityViewModel::class.java]
binding.incrementButton.setOnClickListener {
viewModel.incrementValue(getTextToInt())
}
binding.decrementButton.setOnClickListener {
if (binding.textValue.text.isNotEmpty())
viewModel.decrementValue(getTextToInt())
}
viewModel.result.observe(this, Observer {
binding.textValue.text=it.toString()
})
}
private fun getTextToInt():Int{
return if (binding.textValue.text.isNotEmpty())
Integer.parseInt(binding.textValue.text.toString())
else 0
}
}
ActivityViewModel.kt
package com.learning.livedataexample
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class ActivityViewModel:ViewModel() {
private val _result=MutableLiveData<Int>()
val result: LiveData<Int> get() = _result
fun incrementValue(data:Int){
this._result.value=data+1
}
fun decrementValue(data:Int){
this._result.value=data-1
}
}
OUTPUT
Comments
Post a Comment