如何使用自定义 class 类型绑定视图模型变量
How to bind a view model variable with custom class type
什么有效?
XML:
name="viewModel"
type="com. . . . .MyViewModel" />
...
...
...
<android.support.v7.widget.RecyclerView
android:id="@+id/feeds_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
app:items="@{viewModel.feeds}"
/>
MyViewModel class:
private String[] feeds;
...
...
public MyViewModel() {
String[] feeds = new String[] {"foo", "bar"};
setFeeds(feeds);
}
@Bindable
public String[] getFeeds() {
return feeds;
}
public void setFeeds( String[] feeds) {
this.feeds = feeds;
notifyPropertyChanged(BR.feeds);
}
我的活动:
@BindingAdapter({"items"})
public static void myMethod(View view, String[] feeds) {
// Do somthing
}
我想改变什么?
我想将 String[] 更改为 List<Feed>
,但未达到 myMethod。
我的动态 class:
public class Feed {
private String name;
public Feed(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
目前,这个class只包含一个String成员,当然他会包含更多。
在视图模型中像下面这样更改
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);
}
//为 feed 列表实时数据创建 getter 和 setter。
现在 xml
app:items="@{viewModel.feedListLivedata }"
如果您希望将 List 绑定到 RecyclerView。
要遵循的步骤。
1- 使用 app:items
标签在 xml 文件中创建一个 RecyclerView 以设置要绑定到的项目
<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- 为 RecyclerView 列表的行创建布局。项目应该有 SomeObject 作为变量。
<?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- 使用 ListAdapter
,这是新的,它自己和在工作线程上计算行差异,而不是 RecyclerView.Adapter 并将 SomeObject 和 ViewModel 绑定到此适配器。
/**
* 任务列表适配器。具有对 [TaskListViewModel] 的引用以将操作发送回它。
*/
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
}
}
什么有效?
XML:
name="viewModel"
type="com. . . . .MyViewModel" />
...
...
...
<android.support.v7.widget.RecyclerView
android:id="@+id/feeds_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
app:items="@{viewModel.feeds}"
/>
MyViewModel class:
private String[] feeds;
...
...
public MyViewModel() {
String[] feeds = new String[] {"foo", "bar"};
setFeeds(feeds);
}
@Bindable
public String[] getFeeds() {
return feeds;
}
public void setFeeds( String[] feeds) {
this.feeds = feeds;
notifyPropertyChanged(BR.feeds);
}
我的活动:
@BindingAdapter({"items"})
public static void myMethod(View view, String[] feeds) {
// Do somthing
}
我想改变什么?
我想将 String[] 更改为 List<Feed>
,但未达到 myMethod。
我的动态 class:
public class Feed {
private String name;
public Feed(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
目前,这个class只包含一个String成员,当然他会包含更多。
在视图模型中像下面这样更改
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);
}
//为 feed 列表实时数据创建 getter 和 setter。
现在 xml
app:items="@{viewModel.feedListLivedata }"
如果您希望将 List 绑定到 RecyclerView。
要遵循的步骤。
1- 使用 app:items
标签在 xml 文件中创建一个 RecyclerView 以设置要绑定到的项目
<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- 为 RecyclerView 列表的行创建布局。项目应该有 SomeObject 作为变量。
<?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- 使用 ListAdapter
,这是新的,它自己和在工作线程上计算行差异,而不是 RecyclerView.Adapter 并将 SomeObject 和 ViewModel 绑定到此适配器。
/** * 任务列表适配器。具有对 [TaskListViewModel] 的引用以将操作发送回它。 */
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
}
}