强制RecyclerView调用onCreateViewHolder

问题描述 投票:6回答:3

我有一个RecyclerView,可以显示项目列表,小网格或大网格,这可以在运行时更改。根据用户选择的样式,我在onCreateViewHolder中扩展不同的布局。

我还使用layoutManger.setSpanSizeLookUp()在样式之间切换。我的代码看起来像这样

layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            if(showType == ProductAdapter.SHOW_TYPE_SMALL_GRID)
                return 1;
            else
                return columnCount; //show one item per row
        }
    });

@Override
public void onClick(View v) {
    if(showType == ProductAdapter.SHOW_TYPE_SMALL_GRID)
        showType = ProductAdapter.SHOW_TYPE_LARGE_GRID;
    else
        showType = ProductAdapter.SHOW_TYPE_SMALL_GRID;


    int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
    adapter = new ProductAdapter(getActivity(), productList, showType);
    recyclerView.setAdapter(adapter);
    layoutManager.scrollToPosition(firstVisibleItem);
}

问题是强制调用onCreateViewHolder我每次用户更改样式时都会创建一个新对象。还有其他办法吗?!迫使onBindViewHolder()被召回。我只是使用adapter.notifyDataSetChanged()我怎么能得到类似的onCreateViewHolder?

任何不使用多个适配器的解决方案都足够好了!

android android-adapter android-recyclerview
3个回答
9
投票

你需要做的是:

  1. 修改你的Adapter

  • 指定Views可以膨胀的两种类型的Adapter

private static final int LARGE_GRID_ITEM = -1;
private static final int SMALL_GRID_ITEM = -2;
  • 创建一个可以存储当前类型mCurrentType的字段
  • 使用你的Adapter's getItemViewType。例如这样:

@Override
public int getItemViewType (int position) {
    return mCurrentType;
}
  • 在你的createViewHolder中使用viewType来决定你需要创建什么类型的ViewHolder

public final RecyclerView.ViewHolder createViewHolder (ViewGroup parent, int viewType){
    if (viewType == LARGE_GRID_ITEM) {
        //return large grid view holder
    } else {
        //return small grid view holder
    }
}
  • 另外,您可以创建方法:

public void toggleItemViewType () {
    if (mCurrentType == LARGE_GRID_ITEM){
        mCurrentType = SMALL_GRID_ITEM;
    } else {
        mCurrentType = LARGE_GRID_ITEM;
    }
}

public boolean displaysLargeGrid(){
    return mCurrentType == LARGE_GRID_ITEM;
}
  1. 修改您发布的代码:

layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            if (adapter.displaysLargeGrid()) {
                return 1;
            } else {
                return columnCount; //show one item per row
            }
        }
    });

@Override
public void onClick(View v) {
    adapter.toggleItemViewType();
    adapter.notifyDataSetChanged();
}

2
投票

它不是最佳选择,但最好创建一个新的Adapter,它将调用onCreateViewHolder()。这样,您可以通过非常微小的性能问题来避免麻烦。


-2
投票

我遇到了同样的问题,我这样解决了:

我在片段中嵌套了RecyclerView。每当我获得新数据时(例如从数据库中获取),我通过attaching刷新片段的布局并从容器活动中对其进行detaching:

FragmentClass fragment = (FragmentClass) getSupportFragmentManager().getFragments().get(position); // the fragment's position

getSupportFragmentManager().beginTransaction()
                .detach(fragment)
                .attach(fragment)
                .commit();

这样,你也刷新了RecyclerView的布局。但你记住这一点:

您需要获取要分离的片段的CORRECT引用。因此,使用FragmentManager而不是RecyclerView的适配器来保存对片段的引用。否则,当片段尝试保存其状态时,您将收到IllegalStateException。

© www.soinside.com 2019 - 2024. All rights reserved.