FragmentHome
加载layout_home.xml,然后layout_home.xml显示一个recyclerview
和一个名为btnMain
的按钮
recyclerview
包含项目布局layout_voice_item.xml,它显示一个名为btnChild
的按钮。
我使用displayCheckBox : LiveData<Boolean>
来控制是否使用代码android:visibility="@{!aHomeViewModel.displayCheckBox? View.VISIBLE: View.GONE}"
显示btnMain和btnChild。
当我更改displayCheckBox的值时,我发现btnMain
是否可以显示,但是btnChild继续显示,为什么?
FragmentHome.kt
class FragmentHome : Fragment() {
private lateinit var binding: LayoutHomeBinding
private val mHomeViewModel by lazy {
getViewModel {
HomeViewModel(provideRepository(mContext))
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = DataBindingUtil.inflate(
inflater, R.layout.layout_home, container, false
)
binding.lifecycleOwner = this.viewLifecycleOwner
binding.aHomeViewModel=mHomeViewModel
val adapter = VoiceAdapters(mHomeViewModel)
binding.mvoiceList.adapter=adapter
mHomeViewModel.listVoiceBySort.observe(viewLifecycleOwner){
adapter.submitList(it)
}
...
return binding.root
}
}
HomeViewModel.kt
class HomeViewModel(private val mDBVoiceRepository: DBVoiceRepository) : ViewModel() {
private val _displayCheckBox = MutableLiveData<Boolean>(true)
val displayCheckBox : LiveData<Boolean> = _displayCheckBox
fun setCheckBox(isDisplay:Boolean){
_displayCheckBox.value = isDisplay
}
...
}
VoiceAdapters.kt
class VoiceAdapters (private val aHomeViewModel: HomeViewModel):
ListAdapter<MVoice, VoiceAdapters.VoiceViewHolder>(MVoiceDiffCallback()) {
...
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VoiceViewHolder {
return VoiceViewHolder(
LayoutVoiceItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
override fun onBindViewHolder(holder: VoiceViewHolder, position: Int) {
val aMVoice = getItem(position)
holder.bind(aHomeViewModel, aMVoice)
}
inner class VoiceViewHolder (private val binding: LayoutVoiceItemBinding):
RecyclerView.ViewHolder(binding.root) {
fun bind(mHomeViewModel: HomeViewModel, aMVoice: MVoice) {
binding.aHomeViewModel = mHomeViewModel
binding.executePendingBindings()
}
}
...
}
class MVoiceDiffCallback : DiffUtil.ItemCallback<MVoice>() {
...
}
layout_home.xml
<layout 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">
<data>
<import type="android.view.View" />
<variable name="aHomeViewModel"
type="info.dodata.voicerecorder.viewcontrol.HomeViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/mvoice_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/layout_voice_item"
/>
<Button
android:id="@+id/btnMain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{!aHomeViewModel.displayCheckBox? View.VISIBLE: View.GONE}"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
layout_voice_item.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable name="aHomeViewModel"
type="info.dodata.voicerecorder.viewcontrol.HomeViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btnChild"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="@{!aHomeViewModel.displayCheckBox? View.VISIBLE: View.GONE}"
/>
</LinearLayout>
</layout>
答案 0 :(得分:3)
给 LifecycleOwner
一个 LayoutVoiceItemBinding
可能会有帮助。
voiceViewHolder.binding.lifecycleOwner = yourLifecycleOwner
答案 1 :(得分:2)
视图持有者模式并不总是android的一部分,在被广泛采用之前,幼稚的列表实现会导致为提交列表中的每个值渲染一个夸张的视图。 那是极其低效的内存。
采用视图持有者模式后,视图(可视项)只会膨胀到屏幕上可以看到的最大数量(为了平滑滚动,还需要增加一两个)
但是,需要使适配器知道列表数据的更改。
如果列表需要更新,请在 RecyclerView.Adapter对象,例如notifyItemChanged()。布局 然后经理重新绑定所有受影响的视图持有者,从而允许他们的数据 进行更新。
观察displayCheckBox : LiveData<Boolean>
并致电adapter.notifyItemChanged
可能是眼前的问题。
我留下另一个参考,重申视图绑定将不会观察实时数据,但会减少样板代码。
https://developer.android.com/guide/topics/ui/layout/recyclerview#Adapter
还剩下什么? 现在处理了RecyclerView中的所有样板 而您要做的只是困难的部分:从UI加载数据 线程,在有数据更改时通知适配器等。 Android数据绑定只会减少无聊的部分。