1.初步实现
描述:在上个笔记的基础上用livedata包装。上个笔记中在Activity中手动获取ViewModel中的数据这种交互方式,ViewModel 却无法将数据的变化主动通知给Activity。使用LiveData 来包装,然后在Activity中去观察它,就可以 主动将数据变化通知给Activity了。
代码:
1.activity_main.xml,无变化。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/infoText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="32sp"/>
<Button
android:id="@+id/plusOneBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Plus One"/>
<Button
android:id="@+id/clearBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Clear"/>
</LinearLayout>
2.MianViewModelFactory.kt,无变化。
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
class MainViewModelFactory(private val countReserved: Int) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return MainViewModel(countReserved) as T
}
}
3.MianViewModel.kt,改变count。
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class MainViewModel(countReserved: Int) : ViewModel() {
//将counter变量修改成了一个MutableLiveData对象,泛型为Int,表示它包含的是整型数据
val counter = MutableLiveData<Int>()
init {
counter.value = countReserved
}
fun plusOne() {
val count = counter.value ?: 0
counter.value = count + 1
}
fun clear() {
counter.value = 0
}
4.MainActivity.kt,添加观察者,移除撒刷新界面的方法。
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.edit
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.get
class MainActivity : AppCompatActivity() {
lateinit var viewModel: MainViewModel
lateinit var infoText: TextView
lateinit var plusOneBtn: Button
lateinit var clearBtn: Button
lateinit var sharedPreferences: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
infoText = findViewById(R.id.infoText) as TextView
plusOneBtn = findViewById(R.id.plusOneBtn) as Button
clearBtn = findViewById(R.id.clearBtn) as Button
sharedPreferences = getPreferences(Context.MODE_PRIVATE)
val countReserved = sharedPreferences.getInt("count_reserved", 0)
viewModel = ViewModelProvider(this,
MainViewModelFactory(countReserved)).get(MainViewModel::class.java)
plusOneBtn.setOnClickListener {
//调用MainViewModel的plusOne()
viewModel.plusOne()
}
clearBtn.setOnClickListener {
// 调用MainViewModel的clear()
viewModel.clear()
}
//丢弃refreshCounter()
//*观察者
viewModel.counter.observe(this, Observer {
// *第二个参数是一个Observer接口,当counter中包含的数据发生变化时,就会回调到这里
infoText.text = it.toString()
})
}
//refreshCounter()方法丢去
// private fun refreshCounter() {
// infoText.text = viewModel.counter.toString()
// }
override fun onPause() {
super.onPause()
sharedPreferences.edit {
putInt("count_reserved", viewModel.counter.value ?: 0)
}
}
}
2.问题:我们将counter这个可变的LiveData 暴露给了外部。
描述:对MainViewModel中counter封装即可。
代码:
1.MianViewModel.kt,改变count。
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class MainViewModel(countReserved: Int) : ViewModel() {
// private修饰,counter变量改名为_counter变量
private val _counter = MutableLiveData<Int>()
// 供了一个公共的只读属性 counter 来访问这个数据,在ViewModel内部使用_counter 进行修改和计算,而外部只能通过 counter 来获取数据。
val counter: LiveData<Int>
get() = _counter
init {
_counter.value = countReserved
}
fun plusOne() {
val count = counter.value ?: 0
_counter.value = count + 1
}
fun clear() {
_counter.value = 0
}
}
2.其余代码不变。