Bin*_*ink 8 android-recyclerview android-databinding android-room android-livedata android-viewmodel
Android 开发新手,我\xe2\x80\x99m 试图将我的注意力集中在与 RecyclerView、ViewModel、Room 和 LiveData 结合的双向数据绑定上。我理解单向绑定,但不能\xe2\x80\x99t 找出双向。
\n\n简而言之,我\xe2\x80\x99d 希望能够点击 id/switch_enabled 开关并更新 Db 以反映这一点(然后我计划利用它来更新类/Db 中的其他成员)。我认为我需要一些帮助来设置 ViewModel 上的 set(value) 并在 Db 中更新正确的 RecyclerView 项目,但我\xe2\x80\x99m 不确定如何执行此操作,或者这是否是正确或最佳的方法。
\n\n谢谢。
\n\n班级:
\n\ndata class Person (@ColumnInfo(name = "first_name") val firstName: String,\n @ColumnInfo(name = "last_name") val lastName: String,\n\n //...\n\n val enabled: Boolean = true\n){\n @PrimaryKey(autoGenerate = true)\n var id: Long = 0\n}\nRun Code Online (Sandbox Code Playgroud)\n\nRecyclerView 的布局详细信息:
\n\n<layout xmlns:android="http://schemas.android.com/apk/res/android"\n xmlns:app="http://schemas.android.com/apk/res-auto"\n xmlns:tools="http://schemas.android.com/tools">\n\n <data>\n <variable\n name="p" type="com.example.data.Person" />\n </data>\n\n <androidx.constraintlayout.widget.ConstraintLayout\n android:id="@+id/constraintLayout"\n android:layout_width="match_parent"\n android:layout_height="wrap_content">\n\n <TextView\n android:id="@+id/first_name"\n android:layout_width="wrap_content"\n android:layout_height="wrap_content"\n android:text="@{p.firstName}"\n app:layout_constraintStart_toStartOf="parent"\n app:layout_constraintTop_toTopOf="parent"\n tools:text="John" />\n\n <TextView\n android:id="@+id/last_name"\n android:layout_width="wrap_content"\n android:layout_height="wrap_content"\n android:ellipsize="end"\n android:text="@{\' \' + p.lastName}"\n app:layout_constraintStart_toEndOf="@id/first_name"\n app:layout_constraintTop_toTopOf="parent"\n tools:text=" Doubtfire" />\n\n <Switch\n android:id="@+id/switch_enabled"\n android:layout_width="wrap_content"\n android:layout_height="wrap_content"\n android:checked="@={p.enabled}"\n app:layout_constraintBaseline_toBaselineOf="@id/last_name"\n app:layout_constraintEnd_toEndOf="parent" />\n\n <!--...-->\n\n </androidx.constraintlayout.widget.ConstraintLayout>\n</layout>\nRun Code Online (Sandbox Code Playgroud)\n\n视图模型:
\n\nclass MainViewModel(private val repository: DataRepository) : ViewModel() {\n private val _people: LiveData<List<Person>>\n// @Bindable?\n// @get:Bindable?\n var people: LiveData<List<Person>>\n @Bindable\n get() = _people\n set(value) {\n //Find out which member of the class is being changed and update the Db?\n Log.d(TAG, "Value for set is $value!")\n }\n init {\n _people = repository.livePeople()\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n分段:
\n\noverride fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,\n savedInstanceState: Bundle?): View? {\n val binding = FragmentPeopleBinding.inflate(inflater, container, false)\n val context = context ?: return binding.root\n\n val factory = Utilities.provideMainViewModelFactory(context)\n viewModel = ViewModelProviders.of(requireActivity(), factory).get(MainViewModel::class.java)\n\n val adapter = PeopleViewAdapter()\n viewModel.people.observe(this, Observer<List<Person>> {\n adapter.submitList(it)\n })\n\n binding.apply {\n vm = viewModel\n setLifecycleOwner(this@PeopleFragment)\n executePendingBindings()\n rvPeopleDetails.adapter = adapter\n }\n return binding.root\n}\nRun Code Online (Sandbox Code Playgroud)\n\n列表适配器:
\n\nclass PeopleViewAdapter: ListAdapter<Person, PeopleViewAdapter.ViewHolder>(PeopleDiffCallback()) {\n class PeopleDiffCallback : DiffUtil.ItemCallback<Person>() {\n override fun areItemsTheSame(oldItem: Person, newItem: Person): Boolean {\n return oldItem.id == newItem.id\n }\n\n override fun areContentsTheSame(oldItem: Person, newItem: Person): Boolean {\n return oldItem.number == newItem.number\n }\n }\n\n class ViewHolder(val binding: FragmentPeopleDetailBinding) : RecyclerView.ViewHolder(binding.root) {\n\n fun bind(person: Person) {\n binding.p = person\n }\n }\n\n @NonNull\n override fun onCreateViewHolder(@NonNull parent: ViewGroup, viewType: Int): ViewHolder =\n ViewHolder(FragmentPeopleDetailBinding.inflate(LayoutInflater.from(parent.context), parent, false))\n\n @NonNull\n override fun onBindViewHolder(@NonNull holder: ViewHolder, position: Int) {\n holder.apply {\n bind(getItem(position))\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
我刚刚遇到了同样的问题,即使用 ViewModel 和 RecyclerView 列表在 MVVM 架构中设置双向数据绑定。我确定在这种情况下不可能或不值得努力让两种方式绑定工作,因为您没有直接使用 recyclerview 项布局中的视图模型(您使用的布局变量是 Person 类型,而不是你的视图模型)。
我建议实际上将视图模型添加为布局变量,然后android:onClick="@{() -> viewmodel.onSwitchClicked()}"在视图模型中使用并实现该方法。
在这里查看我的项目的详细信息: https: //github.com/linucksrox/ReminderList
| 归档时间: |
|
| 查看次数: |
5184 次 |
| 最近记录: |