What works?
XML:
name=\"viewModel\"
type=\"com. . . . .MyViewModel\" />
...
...
...
IF you wish bind List to RecyclerView.
Steps to follow.
1- Create a RecyclerView inside xml files with app:items
tag to set items to bind to
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:id="@+id/recycler_view"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:items="@{viewmodel.items}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
2- Create layout for rows of RecyclerView lists. Items should have SomeObject as variable.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.widget.CompoundButton" />
<variable
name="task"
type="com...data.model.Task" />
<variable
name="viewmodel"
type="com...TaskListViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:onClick="@{() -> viewmodel.openTask(task.id)}">
<CheckBox
android:id="@+id/complete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:onClick="@{(view) -> viewmodel.completeTask(task, ((CompoundButton)view).isChecked())}"
android:checked="@{task.completed}" />
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:text="@{task.titleForList}"
app:completedTask="@{task.completed}" />
</LinearLayout>
</layout>
3- Use ListAdapter
, this is new and calculates line differences by itself and on a worker thread, instead of RecyclerView.Adapter and bind SomeObject and ViewModel to this adapter.
/** * Adapter for the task list. Has a reference to the [TaskListViewModel] to send actions back to it. */
class TasksAdapter(private val viewModel: TaskListViewModel) :
ListAdapter<Task, CustomViewHolder>(TaskDiffCallback()) {
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
val item = getItem(position)
holder.bind(viewModel, item)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {
return CustomViewHolder.from(parent)
}
class CustomViewHolder private constructor(val binding: TaskItemBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(viewModel: TaskListViewModel, item: Task) {
binding.viewmodel = viewModel
binding.task = item
binding.executePendingBindings()
}
companion object {
fun from(parent: ViewGroup): CustomViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = TaskItemBinding.inflate(layoutInflater, parent, false)
return CustomViewHolder(binding)
}
}
}
}
/**
* Callback for calculating the diff between two non-null items in a list.
*
* Used by ListAdapter to calculate the minimum number of changes between and old list and a new
* list that's been passed to `submitList`.
*/
class TaskDiffCallback : DiffUtil.ItemCallback<Task>() {
override fun areItemsTheSame(oldItem: Task, newItem: Task): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Task, newItem: Task): Boolean {
return oldItem == newItem
}
}
Change this like below in viewmodel
private MutableLiveData<List<Feed>> feedListLivedata = new MutableLiveData<>();;
public MyViewModel() {
//create a list of feed here
setFeeds(feeds);
}
public void setFeeds( List<Feed> feeds) {
feedListLivedata .postValue(feeds);
}
//create getter and setter for feed list live data.
And now in xml
app:items="@{viewModel.feedListLivedata }"