从ViewModel启动DialogFragment的推荐方法是什么?

时间:2017-03-14 10:13:14

标签: java android mvvm android-databinding

我在Recyclerview中有一个列表对象。当长按一个项目时,我想显示一个对话框,其中包含单击该项目的数据。

Recyclerview正在为每个项目使用数据绑定,并且我可以在长按时使用Log显示所选项目中的数据。

但是,在尝试显示对话框时,您需要转到Activity,不建议在ViewModel对象中使用。{/ p>

那么如何显示对话框?

谢谢,Ove

5 个答案:

答案 0 :(得分:7)

从概念上讲,ViewModel让我觉得从错误的位置启动Dialog。为了更清楚地做到这一点,我将RecyclerView.ViewHolder传递到布局中,并在ViewHolder上有一个方法,在RecyclerView.Adapter上触发自定义侦听器。然后,任何订阅该侦听器(Activity / Fragment)的人都可以启动Dialog。可能看起来有点迂回,但我不认为列表项的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);
            }
        }
    }
}

答案 1 :(得分:4)

请参阅数据绑定库的官方文档的Variables部分。在那里你可以找到一个可以使用的变量context

  

根据需要,生成一个名为context的特殊变量,用于绑定表达式。上下文的值是来自根视图getContext()的上下文。上下文变量将被具有该名称的显式变量声明覆盖。

基本上你可以把它传递给另一个变量,比如viewModel,从那里显示对话框。

android:onClick="@{v -> viewModel.showDialog(context)}"

答案 2 :(得分:1)

我认为对recyclerview使用绑定适配器,并将适配器置于ViewModel中,然后使viewmodel为片段模型,并为xml本身中的setAdapter方法传递适配器。

答案 3 :(得分:0)

因此,您可以使用项目的上下文(例如itemView.getContext())来显示AlertDialog

答案 4 :(得分:0)

来自Bayoudh的提示让我朝着正确的方向前进,但是我发布了这个以便将各个部分放在一起。以下是可点击的cardview。由于我的ViewModel没有对活动的引用,因此我们必须将相关视图作为参数传递。

<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中使用它来获取Bayoudh声明的view.getContext()上下文。