【问题标题】:Update RecyclerView from DialogFragment and main Activity从 DialogFragment 和主 Activity 更新 RecyclerView
【发布时间】:2015-06-30 06:44:03
【问题描述】:

最好的模式是什么。我做了一些解决方法,但我觉得这是一个糟糕的模式。

我的场景。

我有主活动

MainActivity.java

在这个活动中,我正在使用 RecyclerView 加载 Fragment。

ListFragment.java

我还有 DialogFragmentItemAdapter

我正在从适配器显示 DialogFragment

完整的适配器代码

public class TypeAdapter extends RecyclerView.Adapter<CostTypeAdapter.ViewHolder> {
    private static final String TAG = "TypeAdapter";
    private List<CostType> mCostsType;
    private Context mContext;

public CostTypeAdapter(Context context, List<CostType> coststype) {
    mContext = context;
    mCostsType = coststype;

}

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    // Create a new view.
    View v = LayoutInflater.from(viewGroup.getContext())
            .inflate(R.layout.costtype_row, viewGroup, false);

    return new ViewHolder(v);
}

// BEGIN_INCLUDE(recyclerViewOnBindViewHolder)
@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
    //Log.d(TAG, "Element " + position + " set.");
    String Name = mCostsType.get(position).getName();
    viewHolder.tvName.setText(Name);

    //mView click
    viewHolder.cardView.setPreventCornerOverlap(false);
    viewHolder.cardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Dialog here
            FragmentActivity activity = (FragmentActivity)(mContext);
            FragmentManager fm = activity.getSupportFragmentManager();

            CostType costType = new CostType();
            costType.setTypeID(mCostsType.get(position).getTypeID());
            costType.setName(mType.get(position).getName());
            costType.setPriority(0);
            CostsTypeDialogFragment alertDialog = CostsTypeDialogFragment.newInstance(costType);
            alertDialog.show(fm, "cost_type");

        }
    });


}
// END_INCLUDE(recyclerViewOnCreateViewHolder)

public void refreshList() {
    this.notifyDataSetChanged();
    System.out.println("refreshList");

}



@Override
public int getItemCount() {
    return mType.size();
}

/**
 * Provide a reference to the type of views that you are using (custom ViewHolder)
 */
public static class ViewHolder extends RecyclerView.ViewHolder {
    private final TextView tvName;
    private final CardView cardView;

    public ViewHolder(View v) {
        super(v);

        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "Element " + getPosition() + " clicked.");

            }
        });
        tvName = (TextView) v.findViewById(R.id.tvName);
        cardView = (CardView) v.findViewById(R.id.card_view);
    }

}



}

DialogFragment.java 我有此对话框的侦听器以与 MainActivity 进行通信

    onDialogCloseListener mListener;
    // Container Activity must implement this interface
    public interface onDialogCloseListener {
        public void onDialogClose();
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (onDialogCloseListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnDialogClose listener");
        }
    }
    private List<MyType> mType;

    ...

从对话框中单击:

mListener.onDialogClose();

这个对话框有一些按钮。其中之一是例如修改/删除回收列表中的项目。在这个对话框中,我有 onDialogCloseListener 接口。我正在我的 MainActivity 上使用。

MainActivity.java

public class MainActivity extends BaseActivity implements DialogFragment.onDialogCloseListener {

    ... 
    @Override
    public void onDialogClose() {

        RecyclerView mRecyclerView;
        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);

        //not working
        mRecyclerView.getAdapter().notifyDataSetChanged();
    }

我可以通过这种方式使用 Activity 中的 mRecyclerView。例如,我可以让它不可见。但是 notifyDataSetChanged 不起作用。

我的解决方法是创建新的适配器 - 新的 sql 查询、新的对象列表并为 RecyclerView 再次设置它。但这可能不是一个好方法。因为我不能保持滚动位置。

但是如何与适配器建立连接呢?我希望能够添加动画,例如删除项目。

编辑:

跑步

mRecyclerView.getAdapter().notifyItemRemoved(0);

在 onDialogClose 中效果很好。列表已刷新。但是当我想对

做同样的事情时
mRecyclerView.getAdapter().notifyDataSetChanged();

mRecyclerView.getAdapter().notifyItemChanged(0);

列表未刷新。

【问题讨论】:

  • 只需要通知适配器上的数据集发生变化吗?
  • @Onheiron 这将是最简单的方法,但我读到 RecyclerView 并不那么容易。如果有仅使用 notifyDataSetChanged 的​​选项,那么是的。但我需要能够从适配器获取项目。例如在删除显示动画时,保持滚动位置。
  • 您能发布您的完整适配器代码吗?
  • @Onheiron 当然。已编辑。
  • 另一件事。这是有效的: mRecyclerView.getAdapter().notifyItemRemoved(0) 删除效果很好。我可以看到动画。所以问题是要为编辑记录实现类似的东西。例如:mRecyclerView.getAdapter().notifyItemChanged(16) 不刷新列表。

标签: android android-adapter android-recyclerview dialogfragment


【解决方案1】:

建议 1:不要在适配器类中显示对话框,让您的 onClickActivity 中触发您自己的侦听器,例如onItemClicked(CostType costType)

class MyAdapter extends RecyclerView.Adapter .. {

    public interface OnItemClickListener {
        void onItemClicked(CostType costType);
    }

    private OnItemClickListener mListener;

    // setter and getter for OnitemClickListener

    // inside onBindViewHolder
    viewHolder.cardView.setOnClickListener(new View.OnClickListener() {

      @Override
      public void onClick(View v) {
        CostType costType = new CostType();
        costType.setTypeID(mCostsType.get(position).getTypeID());
        costType.setName(mType.get(position).getName());
        costType.setPriority(0);
        mListener.onItemClicked(costType);
      }

}

class MyActivity extends Activity {

    // inside onCreate
    adapter.setOnItemClickListener(new ...);

}

建议2:如果你需要将结果从Fragment B传递到Fragment A,你不需要使用activity,而是使用setTargetFragment/getTargetFragment方法。

// inside MyListFragment
MyDialogFragment frag = MyDialogFragment.newInstance();
frag.setTargetFragment(this, 0);
// commit transaction

// inside MyDialogFragment to trigger listener, make sure MyDialogFragment
// implement OnDialogCloseListener interface
((MyListFragment)getTargetFragment()).onDialogClose();

【讨论】:

  • 谢谢。这就是为什么我要求好的模式。所以我应该将我的 onClick 移动到 MainActivity(而不是片段活动)。但如何做到这一点。和我用 DialogFragment 监听器做的一样吗?
  • 你已经从我这里获得了 +1。但这可能无法解决我更新 recyclerview 列表的问题。我应该在哪里添加 notifyDataSetChanged()。在 MyActivity 中它不起作用。可能将这段代码移到这里不会改变这一点,但我会尝试。
  • @adek 尝试执行以下操作: 1) 确保调用了 onDialogClose 方法。 2) 调用notifyDataSetChanged 方法后调用onBindViewHolder? 3) 创建适配器时,将适配器的引用作为活动中的类变量。例如。将mRecyclerView.getAdapter().notifyDataSetChanged() 替换为mAdapter.notifyDataSetChanged()
  • OK 但 mAdapter 在 FragmentList 中。 OnDialog 调用在 MyActivity 类中。 OnAttach 连接到主要活动。但是从主要活动中,我可以获得 mRecyclerView 参考 - 例如 mRecyclerView 可见性更改有效。所以 getAdapter() 在我看来应该可以工作。
  • @adek 你是对的,你的代码应该可以正常工作。我添加了另一个建议 2。
猜你喜欢
  • 1970-01-01
  • 2019-05-24
  • 1970-01-01
  • 1970-01-01
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
  • 1970-01-01
相关资源
最近更新 更多