In the previous tutorial we learned about one of the Android Architecture Components, ViewModel with LiveData , we have seen example using ViewModel how objects survives configuration changes (On Screen-Rotate) there we did'nt create ViewModel on our own by default ViewModelProviders instantiate ViewModels with no arg constructor.
So if I have a ViewModel with multiple arguments, then I need to use a Factory that I can pass to ViewModelProviders to use when an instance of ViewModel is required let's see sample example for demo .
1. Gradle
Add ViewModel Architecture Component dependency to gradle .
file: build.gradle(app)
dependencies { implementation "android.arch.lifecycle:extensions:1.1.1" annotationProcessor "android.arch.lifecycle:compiler:1.1.1" }
2. API Helper Class
Create a class APIHelper , this is class reference we pass as argument to ViewModel .
package com.tutorialsbuzz.viewmodelfactorysample.data class ApiHelper { fun getUserInfo(): String = (0..10).random().toString() + " Hello World" }
3. ViewModel
- Create a MainViewModel by extending ViewModel class .
- Constructor of MainViewModel takes APIHelper reference .
- Define a LiveData by wrapping to the String data variable .
package com.tutorialsbuzz.viewmodelfactorysample class MainViewModel(private val apiHelper: ApiHelper) : ViewModel() { val userInfo = MutableLiveData<String>().apply { postValue("") } fun getUsersInfo() { userInfo.postValue(apiHelper.getUserInfo()) } }
4. ViewModelProvider Factory
- Create ViewModelFactory by extending ViewModelProvider.Factory interface .
- Override the create function which creates a new instance of the given class .
- @param modelClass a class whose instance is requested
- @param <T> the type parameter for the ViewModel.
- @return a newly created ViewModel
package com.tutorialsbuzz.viewmodelfactorysample class ViewModelFactory(private val apiHelper: ApiHelper) : ViewModelProvider.Factory { override fun <T : ViewModel?> create(modelClass: Class<T>): T { if (modelClass.isAssignableFrom(MainViewModel::class.java)) { return MainViewModel(apiHelper) as T } throw IllegalArgumentException("Unknown class name") } }
5. XML
file : activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:gravity="center" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:id="@+id/tvNumber" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:gravity="center" android:text="" android:textSize="30sp" /> <Button android:id="@+id/update" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="30dp" android:gravity="center" android:text="update" android:textSize="30sp" /> </LinearLayout>
6. MainActivity
- Create a koltin class MainActivity.kt and extend it to AppCompatActivity class .
- Override onCreate function and set the content of this MainActivity with above defined xml layout (activity_main.xml).
Setting Up ViewModel :
- ViewModelProviders is a utility class that provides ViewModels for a given Activity scope .
- ViewModelProviders.Factory interface are responsible to instantiate ViewModels.
- ViewModelProvider.of is a static function .
Parameter :
1. An activity, in whose scope ViewModels should be retained
2. Factory to instantiate new ViewModels
Returns :
a ViewModelProvider instance
The get function on ViewModelProvider returns ViewModel instance of the given Type .
viewModel = ViewModelProviders.of(this,ViewModelFactory(ApiHelper())) .get(MainViewModel::class.java)
Setting Up Observer :
LiveData is defined in ViewModel , if any change change to live data can be observed .
viewModel.userInfo.observe(this, { tvNumber.text = it })
Main Activity Complete code .
file : MainActivity.kt
package com.tutorialsbuzz.viewmodelfactorysample class MainActivity : AppCompatActivity() { private lateinit var viewModel: MainViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setupViewModel() setUpObserver() update.setOnClickListener({ viewModel.getUsersInfo() }) } private fun setupViewModel() { viewModel = ViewModelProviders.of( this, ViewModelFactory(ApiHelper()) ).get(MainViewModel::class.java) } private fun setUpObserver() { viewModel.userInfo.observe(this, { tvNumber.text = it }) } }
No comments:
Post a Comment