从 ViewModel 启动 DialogFragment 的推荐方法是什么?
What is the recommended way to launch a DialogFragment from a ViewModel?
我在 Recyclerview
中有一个列表对象。当长按一个项目时,我想显示一个对话框,其中包含单击项目的数据。
Recyclerview
正在为每个项目使用数据绑定,我可以在长按时使用 Log 显示所选项目的数据。
但是,当尝试显示对话框时,您需要访问 Activity
,不建议在 ViewModel
对象中使用它。
那么如何显示对话框?
谢谢,欧维
因此您可以使用项目的上下文 itemView.getContext()
来显示 AlertDialog
Bayoudh 的提示将我引向了正确的方向,但我发布这个是为了将各个部分放在一起。下面是一个可点击的卡片视图。由于我的 ViewModel
没有引用 activity 我们必须将有问题的视图作为参数传递。
<android.support.v7.widget.CardView
android:id="@+id/cardviewContact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/text_margin_0.5x"
android:layout_marginRight="@dimen/text_margin_0.5x"
android:layout_marginTop="@dimen/text_margin_0.5x"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:minHeight="50dp"
card_view:cardCornerRadius="4dp"
android:onClick="@{(view) -> viewModel.onClick(view)}" >
android:onClick="@{(view) -> viewModel.onClick(view)}"
语句将当前视图作为参数,因此您可以在 ViewModel 中使用它来获取具有 view.getContext()
的上下文,如 Bayoudh 所述。
请参阅数据绑定库官方文档的 Variables 部分。在那里你找到了一个你可以使用的变量context
。
A special variable named context is generated for use in binding expressions as needed. The value for context is the Context from the root View's getContext()
. The context variable will be overridden by an explicit variable declaration with that name.
基本上您可以将它传递给另一个变量,例如 viewModel
以从那里显示对话框。
android:onClick="@{v -> viewModel.showDialog(context)}"
从概念上讲,我认为 ViewModel 是启动对话框的错误位置。为了更干净地做到这一点,我会将 RecyclerView.ViewHolder 传递到布局中,并在 ViewHolder 上使用一个方法来触发 RecyclerView.Adapter 上的自定义侦听器。然后订阅该侦听器 (Activity/Fragment) 的任何人都可以启动该对话框。可能看起来有点迂回,但我认为列表项的 ViewModel 不应该了解或控制其环境。
这是一个例子。这是使用数据绑定和 ViewModel 处理 RecyclerView 项目点击的通用模式。这不是一个完整的示例,只是突出显示此特定模式的代码。
布局:
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data>
<variable
name="viewHolder"
type="com.example.ViewHolder"
/>
<variable
name="viewModel"
type="com.example.ViewModel"
/>
</data>
<com.example.View
android:layout_width="match_parent"
android:layout_height="24dp"
android:onClick="@{() -> viewHolder.onClick(viewModel)}"
/>
</layout>
适配器:
class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
public interface SelectionListener {
void onSelectionChanged(int newPosition, ViewModel viewModel);
}
private @NonNull WeakReference<SelectionListener> selectionListener =
new WeakReference<>(null);
public void setSelectionListener(@Nullable SelectionListener listener) {
selectionListener = new WeakReference<>(listener);
}
public class ViewHolder extends RecyclerView.ViewHolder<ViewBinding> {
ViewHolder(ViewBinding binding) {
super(binding.getRoot());
binding.setViewHolder(this);
binding.setViewModel(new ViewModel());
}
public void onClick(ViewModel viewModel) {
SelectionListener listener = selectionListener.get();
if (listener != null) {
listener.onSelectionChanged(getAdapterPosition(), viewModel);
}
}
}
}
我想为recyclerview使用一个绑定适配器,然后将适配器n ViewModel,然后使viewmodel成为片段的模型,并在xml本身的setAdapter方法中传递适配器。
我在 Recyclerview
中有一个列表对象。当长按一个项目时,我想显示一个对话框,其中包含单击项目的数据。
Recyclerview
正在为每个项目使用数据绑定,我可以在长按时使用 Log 显示所选项目的数据。
但是,当尝试显示对话框时,您需要访问 Activity
,不建议在 ViewModel
对象中使用它。
那么如何显示对话框?
谢谢,欧维
因此您可以使用项目的上下文 itemView.getContext()
来显示 AlertDialog
Bayoudh 的提示将我引向了正确的方向,但我发布这个是为了将各个部分放在一起。下面是一个可点击的卡片视图。由于我的 ViewModel
没有引用 activity 我们必须将有问题的视图作为参数传递。
<android.support.v7.widget.CardView
android:id="@+id/cardviewContact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/text_margin_0.5x"
android:layout_marginRight="@dimen/text_margin_0.5x"
android:layout_marginTop="@dimen/text_margin_0.5x"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:minHeight="50dp"
card_view:cardCornerRadius="4dp"
android:onClick="@{(view) -> viewModel.onClick(view)}" >
android:onClick="@{(view) -> viewModel.onClick(view)}"
语句将当前视图作为参数,因此您可以在 ViewModel 中使用它来获取具有 view.getContext()
的上下文,如 Bayoudh 所述。
请参阅数据绑定库官方文档的 Variables 部分。在那里你找到了一个你可以使用的变量context
。
A special variable named context is generated for use in binding expressions as needed. The value for context is the Context from the root View's
getContext()
. The context variable will be overridden by an explicit variable declaration with that name.
基本上您可以将它传递给另一个变量,例如 viewModel
以从那里显示对话框。
android:onClick="@{v -> viewModel.showDialog(context)}"
从概念上讲,我认为 ViewModel 是启动对话框的错误位置。为了更干净地做到这一点,我会将 RecyclerView.ViewHolder 传递到布局中,并在 ViewHolder 上使用一个方法来触发 RecyclerView.Adapter 上的自定义侦听器。然后订阅该侦听器 (Activity/Fragment) 的任何人都可以启动该对话框。可能看起来有点迂回,但我认为列表项的 ViewModel 不应该了解或控制其环境。
这是一个例子。这是使用数据绑定和 ViewModel 处理 RecyclerView 项目点击的通用模式。这不是一个完整的示例,只是突出显示此特定模式的代码。
布局:
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data>
<variable
name="viewHolder"
type="com.example.ViewHolder"
/>
<variable
name="viewModel"
type="com.example.ViewModel"
/>
</data>
<com.example.View
android:layout_width="match_parent"
android:layout_height="24dp"
android:onClick="@{() -> viewHolder.onClick(viewModel)}"
/>
</layout>
适配器:
class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
public interface SelectionListener {
void onSelectionChanged(int newPosition, ViewModel viewModel);
}
private @NonNull WeakReference<SelectionListener> selectionListener =
new WeakReference<>(null);
public void setSelectionListener(@Nullable SelectionListener listener) {
selectionListener = new WeakReference<>(listener);
}
public class ViewHolder extends RecyclerView.ViewHolder<ViewBinding> {
ViewHolder(ViewBinding binding) {
super(binding.getRoot());
binding.setViewHolder(this);
binding.setViewModel(new ViewModel());
}
public void onClick(ViewModel viewModel) {
SelectionListener listener = selectionListener.get();
if (listener != null) {
listener.onSelectionChanged(getAdapterPosition(), viewModel);
}
}
}
}
我想为recyclerview使用一个绑定适配器,然后将适配器n ViewModel,然后使viewmodel成为片段的模型,并在xml本身的setAdapter方法中传递适配器。