Android 从 RecyclerView 中删除子项

Android removing of subitems from RecyclerView

我的 RecyclerView 有一个适配器。适配器的每个项目都有 ImageView 和另一个适配器 RecyclerView,其中每个项目也有 ImageView。我必须单击子项目并转到其详细信息视图。在那个视图中,当我点击 REMOVE 按钮时,它必须删除这个子项目。所以我有几个问题:

  1. 我在主适配器中实现了方法,它有两个参数:在主列表中的位置和在子列表中的位置。这就是我尝试删除它的方式。问题是,当我在一个位置删除一个子项时,它会在另一个位置删除相同的子项(我使用假数据,其中一些是相同的)。
  2. 删除一个子项目后,当我尝试删除第二个时,它没有删除。我在调试模式下检查过,看到子项列表的大小变成了开始时的大小。

这里有我的适配器的代码。在主适配器中,我有内部 class 用于带有子项的适配器:

public class PhotoWithDuplicatesAdapterTest extends RecyclerView.Adapter<PhotoWithDuplicatesAdapterTest.ViewHolder> {

    private Context mContext;
    private List<MediaWithDuplicatesTest> mTests;
    private OnDuplicateClickListener mListener;

    public PhotoWithDuplicatesAdapterTest(Context context, List<MediaWithDuplicatesTest> tests) {
        mContext = context;
        mTests = tests;
    }

    public interface OnDuplicateClickListener {
        void onDuplicateClick(int photoPosition, int duplicatePosition);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.photo_with_duplicates_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Picasso.with(mContext)
                .load(mTests.get(position).getPhoto())
                .fit()
                .centerCrop()
                .into(holder.mPhotoImageView);
        DuplicateAdapter adapter = new DuplicateAdapter(mContext, position, mTests.get(position).getDuplicates());
        adapter.setOnDuplicateClickListener(new DuplicateAdapter.OnDuplicateClickListener() {
            @Override
            public void onDuplicateClick(int photoPosition, int duplicatePosition) {
                if (mListener != null) mListener.onDuplicateClick(photoPosition, duplicatePosition);
            }
        });
        LinearLayoutManager manager = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false);
        holder.mDuplicatesRecyclerView.setLayoutManager(manager);
        holder.mDuplicatesRecyclerView.setAdapter(adapter);
    }

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

    public void setOnDuplicateClickListener(OnDuplicateClickListener listener) {
        mListener = listener;
    }

    public void removeDuplicate(int photoPosition, int duplicatePosition) {
        List<String> duplicates = mTests.get(photoPosition).getDuplicates();
        duplicates.remove(duplicatePosition);
        if (duplicates.size() == 0) {
            mTests.remove(photoPosition);
            notifyItemRemoved(photoPosition);
        } else notifyItemChanged(photoPosition);
    }

    public String getDuplicate(int photoPosition, int duplicatePosition) {
        return mTests.get(photoPosition).getDuplicates().get(duplicatePosition);
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        @Bind(R.id.iv_photo) SquareImageView mPhotoImageView;
        @Bind(R.id.rv_duplicates) RecyclerView mDuplicatesRecyclerView;

        public ViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }

    public static class DuplicateAdapter extends RecyclerView.Adapter<DuplicateAdapter.ViewHolder> {

        private Context mContext;
        private int mPhotoPosition;
        private List<String> mDuplicates;
        private OnDuplicateClickListener mListener;

        public DuplicateAdapter(Context context, int photoPosition, List<String> duplicates) {
            mContext = context;
            mPhotoPosition = photoPosition;
            mDuplicates = duplicates;
        }

        public interface OnDuplicateClickListener {
            void onDuplicateClick(int photoPosition, int duplicatePosition);
        }

        @Override
        public DuplicateAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.duplicate_item, parent, false);
            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(DuplicateAdapter.ViewHolder holder, int position) {
            Picasso.with(mContext)
                    .load(mDuplicates.get(position))
                    .fit()
                    .centerCrop()
                    .into(holder.mDuplicateImageView);
        }

        @Override
        public int getItemCount() {
            return mDuplicates == null ? 0 : mDuplicates.size();
        }

        public void setOnDuplicateClickListener(OnDuplicateClickListener listener) {
            mListener = listener;
        }

        public class ViewHolder extends RecyclerView.ViewHolder {

            @Bind(R.id.iv_duplicate) SquareImageView mDuplicateImageView;

            @OnClick(R.id.iv_duplicate)
            void onDuplicateClick() {
                if (mListener != null) mListener.onDuplicateClick(mPhotoPosition, getAdapterPosition());
            }

            public ViewHolder(View itemView) {
                super(itemView);
                ButterKnife.bind(this, itemView);
            }
        }
    }
}

这就是我所说的删除子项目的方式(在 Activity 中)

// implementing of DuplicatesFragment.OnRemoveListener
@Override
public void onRemove(int photoPosition, int duplicatePosition) {
    fm.popBackStackImmediate();
    Fragment fragment = fm.findFragmentById(R.id.fragment_container);
    if (fragment instanceof DuplicatesFragment) {
        DuplicatesFragment duplicatesFragment = (DuplicatesFragment) fragment;
        duplicatesFragment.removeDuplicate(photoPosition, duplicatePosition);
    }
}

DuplicatesFragment中的removeDuplicate方法:

public void removeDuplicate(int photoPosition, int duplicatePosition) {
    if (mAdapter != null) mAdapter.removeDuplicate(photoPosition, duplicatePosition);
}

mAdapter - PhotoWithDuplicatesAdapterTest 的实例。我做错了什么?

看起来是这样的:

MediaWithDuplicatesTest个对象:

public class MediaWithDuplicatesTest {

    private String mPhoto;
    private List<String> mDuplicates;

    public String getPhoto() {
        return mPhoto;
    }

    public void setPhoto(String photo) {
        mPhoto = photo;
    }

    public List<String> getDuplicates() {
        return mDuplicates;
    }

    public void setDuplicates(List<String> duplicates) {
        mDuplicates = duplicates;
    }
}

也许,如果我也 post 创建我的测试数据和适配器的代码会有所帮助:

private void populateRecyclerViewHolder() {
    LinearLayoutManager manager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
    mAdapter = new PhotoWithDuplicatesAdapterTest(getContext(), getFakeData());
    mAdapter.setOnDuplicateClickListener(this);
    mViewHolder.mPhotosWithDuplicatesRecyclerView.setLayoutManager(manager);
    mViewHolder.mPhotosWithDuplicatesRecyclerView.setAdapter(mAdapter);
}

private List<MediaWithDuplicatesTest> getFakeData() {
    List<MediaWithDuplicatesTest> fakeData = new ArrayList<>();
    List<String> fakeDuplicates = getFakeDuplicates();
    for (String fakeDuplicate : fakeDuplicates) {
        MediaWithDuplicatesTest fake = new MediaWithDuplicatesTest();
        fake.setPhoto(fakeDuplicate);
        fake.setDuplicates(fakeDuplicates);
        fakeData.add(fake);
    }
    return fakeData;
}

private List<String> getFakeDuplicates() {
    return new ArrayList<String>() {
        {
            add("http://2.bp.blogspot.com/-CmBgofK7QzU/TVj3u3N1h2I/AAAAAAAADN8/OszBhGvvXRU/s640/tumblr_lg7h9gpbtP1qap9qio1_500.jpeg");
            add("http://www.newcastlewildflower.com.au/wp-content/uploads/2013/05/9fkUCY02te7bqobeZzdT9SEio1_500.jpg");
            add("http://img.ffffound.com/static-data/assets/6/51cc46900bf5fe574293d49c4d9939e0ebfc8ee3_m.jpg");
            add("http://2.bp.blogspot.com/-CmBgofK7QzU/TVj3u3N1h2I/AAAAAAAADN8/OszBhGvvXRU/s640/tumblr_lg7h9gpbtP1qap9qio1_500.jpeg");
            add("http://www.newcastlewildflower.com.au/wp-content/uploads/2013/05/9fkUCY02te7bqobeZzdT9SEio1_500.jpg");
            add("http://img.ffffound.com/static-data/assets/6/51cc46900bf5fe574293d49c4d9939e0ebfc8ee3_m.jpg");
        }
    };
}

好的,我们开始吧。在 private List getFakeData() 方法中,您将相同的 fakeDuplicates 列表传递给主适配器中的所有项目。这意味着他们共享基础数据。对它的更改会反映在根据数据创建的所有视图中。将列表的实例化放在循环中,看看是否有帮助。