当前位置:网站首页>Learning to use livedata and ViewModel will make it easier for you to write business
Learning to use livedata and ViewModel will make it easier for you to write business
2022-07-01 13:34:00 【InfoQ】
Preface :
Introduce
LiveData and ViewModel The relationship between :

LiveData
Use LiveData It has the following advantages :
- UI Match data status
- LiveData Follow the observer pattern . When the underlying data changes ,LiveData Will inform
Observerobject . You can integrate the code in theseObserverObject to update the interface . thus , You don't need to update the interface every time the application data changes , Because the observer will complete the update for you .
- Improve code stability
- Code stability increases throughout the application lifecycle :
- There is no crash when the activity stops . If the application component is inactive , Then these changes are not affected . therefore , You don't have to worry about the lifecycle of application components when updating data . For activities in the background stack , It will not accept any LiveData event
- Memory leaks are reduced , The observer will be bound to Lifecycle object , And self cleaning after its associated life cycle has been destroyed
- Don't worry about unsubscribing from any observer
- If due to configuration changes ( If the equipment rotates ) And recreated Activity or Fragment, It will immediately receive the latest available data .
- No longer need to manually handle the lifecycle
- Interface components just look at relevant data , Does not stop or resume observation .LiveData All of these operations will be managed automatically , Because it can sense the change of related life cycle state when observing .
- Data is always up to date
- If the life cycle becomes inactive , It receives the latest data when it becomes active again . for example , Used to be backstage Activity It will receive the latest data immediately after returning to the foreground .
- Shared resources
- Like the singleton mode , We can also expand our LiveData Object to wrap system services , So that they can be shared in our application . once LiveData Object to connect to system services , Any observer who needs resources can easily watch LiveData object .
In the following cases , Do not use LiveData:
- You need to use a lot of operators on Information , Even though LiveData Provides tools such as transformations , But only Map and switchMap Can help you
- You don't have any contact with information UI Interaction
- You have a one-time asynchronous operation
- You do not have to save cached information to UI in
How to use LiveData
Basic usage process :
class MainViewModel : ViewModel() {
var mycount: MutableLiveData<Int> = MutableLiveData()
}
class MainActivity : AppCompatActivity() {
lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
...
/** Remember that you can never create directly ViewModel example
Be sure to pass ViewModelProvider(ViewModelStoreOwner) Constructor to get .
Because every time you rotate the screen, you will recall onCreate() Method , If you create a new instance every time, you cannot save the data .
After using the above method ,onCreate Method is called again ,
It will return an and MainActivity Associated with a preexisting ViewModel, That's why you save data .*/
viewModel = ViewModelProvider([email protected],ViewModelProvider.
NewInstanceFactory()).get(MainViewModel::class.java)
}
}
/**
* subscribe ViewModel,mycount It's a LiveData type You can observe
* */
viewModel.mycount.observe([email protected]) {
countTv.text = viewModel.mycount.value.toString()
}
// LiveData onchange Will automatically sense the lifecycle No manual operation required
// viewModel.mycount.observe(this, object : Observer<Int> {
// override fun onChanged(t: Int?) {
//
// }
// })
Advanced usage :
// Entity class
data class User(var name: String)
...
//Transformations.map Receive two parameters , The first parameter is for the transformation LiveData The original object , The second parameter is the conversion function .
private val userLiveData: MutableLiveData<User> = MutableLiveData()
val userNames: LiveData<String> = Transformations
.map(userLiveData) { user ->
user.name
}
data class Student
(var englishScore: Double, var mathScore: Double, val scoreTAG: Boolean)
.....
class SwitchMapViewModel:ViewModel {
var studentLiveData = MutableLiveData<Student>()
val transformationsLiveData = Transformations.switchMap(studentLiveData) {
if (it.scoreTAG) {
MutableLiveData(it.englishScore)
} else {
MutableLiveData(it.mathScore)
}
}
}
// When using :
var student = Student()
person.englishScore = 88.2
person.mathScore = 91.3
// Decide which grade to show
person.condition = true
switchMapViewModel.conditionLiveData.postValue(person)
class MediatorLiveDataViewModel : ViewModel() {
var liveDataA = MutableLiveData<String>()
var liveDataB = MutableLiveData<String>()
var mediatorLiveData = MediatorLiveData<String>()
init {
mediatorLiveData.addSource(liveDataA) {
Log.d("This is livedataA", it)
mediatorLiveData.postValue(it)
}
mediatorLiveData.addSource(liveDataB) {
Log.d("This is livedataB", it)
mediatorLiveData.postValue(it)
}
}
}
explain :
- MutableLiveData The parent class is LiveData
- LiveData In the entity class, you can notify the data update of a specified field
- MutableLiveData It is only notified after the entire entity class or data type changes . Details will not be to a field .
Principle Exploration :
- LiveData How it works
- LiveData Of observe Method source code analysis
- LifecycleBoundObserver Source code analysis
- activeStateChanged Source code analysis ( For sticky events )
- postValue and setValue
- considerNotify Determine whether to send data analysis
- Analysis of viscous events
ViewModel
Official profile
Life cycle

Basic usage process :
class MainViewModel : ViewModel() {
...
}
// The first one is ViewModelProvider Direct access to
ViewModelProvider([email protected]).get(MainViewModel::class.java)
// The second kind adopt ViewModelFactory establish
class TestViewModelFactory(private val param: Int) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return TestViewModel(param) as T
}
}
ViewModelProvider([email protected],TestViewModelFactory(0)).get(TestViewModel::class.java)
ViewModel Common use scenarios
- Use ViewModel, After switching between horizontal and vertical screens ,Activity The reconstruction , Data can still be saved
- The same Activity Next ,Fragment Data sharing between
- And LiveData Cooperate to realize code decoupling
ViewModel and onSaveInstanceState The difference between
ViewModel and Context
Case a : Counter — Two Activity Share a ViewModel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class MainViewModel : ViewModel() {
private var _mycount: MutableLiveData<Int> = MutableLiveData()
// Expose only immutable LiveData Externally
val mycount: LiveData<Int> get() = _mycount
init {
// initialization
_mycount.value = 0
}
/**
* mycount.value If it is empty, it will be assigned as 0, If it is not empty, add one
* */
fun add() {
_mycount.value = _mycount.value?.plus(1)
}
/**
* mycount.value If it is empty, it will be assigned as 0, If it is not empty, subtract one , Can be negative
* */
fun reduce() {
_mycount.value = _mycount.value?.minus(1)
}
/**
* Random parameter
* */
fun random() {
val random = (0..100).random()
_mycount.value = random
}
/**
* Clear data
* */
fun clear() {
_mycount.value = 0
}
}
import androidx.lifecycle.*
/**
* Used to mark viewmodel Scope of action
*/
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
annotation
class VMScope(val scopeName: String) {}
private val vMStores = HashMap<String, VMStore>()
fun LifecycleOwner.injectViewModel() {
// Create a store according to the scope
this::class.java.declaredFields.forEach { field ->
field.getAnnotation(VMScope::class.java)?.also { scope ->
val element = scope.scopeName
var store: VMStore
if (vMStores.keys.contains(element)) {
store = vMStores[element]!!
} else {
store = VMStore()
vMStores[element] = store
}
val clazz = field.type as Class<ViewModel>
val vm = ViewModelProvider(store, ViewModelProvider.NewInstanceFactory()).get(clazz)
field.set(this, vm)
}
}
}
class VMStore : ViewModelStoreOwner {
private var vmStore: ViewModelStore? = null
override fun getViewModelStore(): ViewModelStore {
if (vmStore == null)
vmStore = ViewModelStore()
return vmStore!!
}
}
class MainActivity : AppCompatActivity() {
@VMScope("count") // Set scope
lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
injectViewModel()
initEvent()
}
private fun initEvent() {
val cardReduce: CardView = findViewById(R.id.card_reduce)
.....
cardReduce.setOnClickListener {
// Call custom ViewModel The method in
viewModel.reduce()
}
.....
/**
* subscribe ViewModel,mycount It's a LiveData type You can observe
* */
viewModel.mycount.observe([email protected]) {
countTv.text = viewModel.mycount.value.toString()
}
}
In the second Activity The same is true of ...
Case 2 : The same Activity Of the two Fragment Share a ViewModel

class BlankViewModel : ViewModel() {
private val numberLiveData = MutableLiveData<Int>()
private var i = 0
fun getLiveData(): LiveData<Int> {
return numberLiveData
}
fun addOne(){
i++
numberLiveData.value = i
}
}
// Left Fragment
class LeftFragment : Fragment() {
private val viewModel:BlankViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_left, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Yes +1 Button monitoring
left_button.setOnClickListener {
viewModel.addOne()
}
activity?.let {it ->
viewModel.getLiveData().observe(it){
left_text.text = it.toString()
}
}
}
}
// Right Fragment
class RightFragment : Fragment() {
private val viewModel: BlankViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_right, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
right_button.setOnClickListener {
viewModel.addOne()
}
activity?.let { it ->
viewModel.getLiveData().observe(it) {
right_text.text = it.toString()
}
}
}
}
Epilogue
About me
边栏推荐
- Terminal identification technology and management technology
- [Niu Ke's questions -sql big factory interview real questions] no2 User growth scenario (a certain degree of information flow)
- 1.8 new features list
- Detailed explanation of parallel replication examples in MySQL replication
- 啟動solr報錯The stack size specified is too small,Specify at least 328k
- Huawei HMS core joins hands with hypergraph to inject new momentum into 3D GIS
- Anti fraud, refusing to gamble, safe payment | there are many online investment scams, so it's impossible to make money like this
- Report on the current situation and development trend of bidirectional polypropylene composite film industry in the world and China Ⓟ 2022 ~ 2028
- PG basics -- Logical Structure Management (trigger)
- 6. Wiper part
猜你喜欢

SVG钻石样式代码

The best landing practice of cave state in an Internet ⽹⾦ financial technology enterprise

French Data Protection Agency: using Google Analytics or violating gdpr

简单的两个圆球loading加载

介绍一种对 SAP GUI 里的收藏夹事务码管理工具增强的实现方案

开源者的自我修养|为 ShardingSphere 贡献了千万行代码的程序员,后来当了 CEO

What is the future development direction of people with ordinary education, appearance and family background? The career planning after 00 has been made clear

8 popular recommended style layout
![[machine learning] VAE variational self encoder learning notes](/img/38/3eb8d9078b2dcbe780430abb15edcb.png)
[machine learning] VAE variational self encoder learning notes

详细讲解面试的 IO多路复用,select,poll,epoll
随机推荐
1553B environment construction
Detailed explanation of leetcode reconstruction binary tree [easy to understand]
流量管理技术
spark源码阅读总纲
机器学习—性能度量
Yarn重启applications记录恢复
Professor Li Zexiang, Hong Kong University of science and technology: I'm wrong. Why is engineering consciousness more important than the best university?
关于佛萨奇2.0“Meta Force原力元宇宙系统开发逻辑方案(详情)
20个实用的 TypeScript 单行代码汇总
10. Page layout, guess you like it
5G工业网关的科技治超应用 超限超重超速非现场联合执法
Nexus builds NPM dependent private database
3.4 data query in introduction to database system - select (single table query, connection query, nested query, set query, multi table query)
Three questions about scientific entrepreneurship: timing, pain points and important decisions
Google Earth Engine(GEE)——全球人类居住区网格数据 1975-1990-2000-2014 (P2016)
2. Sensor size "recommended collection"
Leetcode第一题:两数之和(3种语言)
刘对(火线安全)-多云环境的风险发现
Colorful five pointed star SVG dynamic web page background JS special effect
Investment analysis and prospect prediction report of global and Chinese p-nitrotoluene industry Ⓙ 2022 ~ 2027