LiveData一般都是和ViewModel配合使用,如果还没有学习过ViewModel的小伙伴可以看一下我之前写的文章:
前置知识
代码演示 1
NumViewModel.kt
class NumViewModel : ViewModel() {
private val _data:MutableLiveData<Int> = MutableLiveData(0)
val data:LiveData<Int> get() = _data
fun updateData(num:Int){
_data.value = num
}
}
我们通过代码可以看到,它的使用是在ViewModel中的。LiveData也能感知生命周期的变化,并且能够观察数据,在数据变化的时候对UI组件做出改变。并且我在这里定义的是不可变的常量,真正改变数据的LivaData被我privater起来了,达到封装的效果。
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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/num_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.391" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="128dp"
android:onClick="add"
android:text="添加"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/num_tv" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var tv:TextView
private lateinit var numViewModel: NumViewModel
@SuppressLint("MissingInflatedId", "SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
tv = findViewById(R.id.num_tv)
numViewModel = ViewModelProvider(this)[NumViewModel::class.java]
tv.text = numViewModel.data.value.toString()
numViewModel.data.observe(this,{
tv.text = it.toString()
})
}
fun add(view: View) {
val num = numViewModel.data.value!! + 1
numViewModel.updateData(num)
Log.i("MainActivity",numViewModel.data.value.toString())
}
}
这里numViewModel.data观察数据变化,就要数据改变了,就更新UI。一行代码就能达到这种效果,而且就算屏幕翻转还有ViewModel兜底,爽啦爽啦😋。
看起来LiveData使用起来很简单嘛,再爽一次!。
代码演示2:Fragment之间的数据共享——SeekBar演示
此案例以SeekBar进行Fragment之间数据共享的演示。(感觉档次瞬间就上来了😚)
最终效果
这也太丝滑了吧!!!😋
SeekBarViewModel.kt
class SeekBarViewModel : ViewModel() {
private val _data:MutableLiveData<Int> = MutableLiveData(0)
val progress:LiveData<Int> get() = _data
fun updateData(progress: Int){
_data.value = progress
}
}
OneFragment.kt
class OneFragment : Fragment() {
private lateinit var seekBarViewModel:SeekBarViewModel
@SuppressLint("MissingInflatedId", "SetTextI18n", "FragmentLiveDataObserve")
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_one,container,false)
val seekBar = view.findViewById<SeekBar>(R.id.seekbar1)
seekBarViewModel = ViewModelProvider(requireActivity())[SeekBarViewModel::class.java]
seekBarViewModel.progress.observe(this,{
seekBar.progress = seekBarViewModel.progress.value!!
})
seekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
seekBarViewModel.updateData(progress)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
return view
}
}
fragment_two.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent">
<SeekBar
android:id="@+id/seekbar1"
android:layout_width="match_parent"
android:max="100"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
第二个Fragment与上面的是u一模一样的,就不贴啦👌
activity_second.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">
<androidx.fragment.app.FragmentContainerView
android:name="com.software.livedata_learn.OneFragment"
android:layout_width="321dp"
android:id="@+id/fragment1"
android:layout_height="251dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.fragment.app.FragmentContainerView
android:name="com.software.livedata_learn.TwoFragment"
android:id="@+id/fragment2"
android:layout_width="321dp"
android:layout_height="251dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fragment1"
app:layout_constraintVertical_bias="0.659" />
</androidx.constraintlayout.widget.ConstraintLayout>
SecondActivity.kt
<?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">
<androidx.fragment.app.FragmentContainerView
android:name="com.software.livedata_learn.OneFragment"
android:layout_width="321dp"
android:id="@+id/fragment1"
android:layout_height="251dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.fragment.app.FragmentContainerView
android:name="com.software.livedata_learn.TwoFragment"
android:id="@+id/fragment2"
android:layout_width="321dp"
android:layout_height="251dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fragment1"
app:layout_constraintVertical_bias="0.659" />
</androidx.constraintlayout.widget.ConstraintLayout>
主要是两个Fragment中ViewModel的ViewModelStoreOwner都是他们的activity,他们的activity还都一样,所以他们的数据就是同步的,一更改数据就会让livadata观察到,这样的效果只需要几行代码,这还不爽?😋
给个关注吧!😋
感觉主包讲的好的可以点个关注哦😚