强制RecyclerView调用onCreateViewHolder

时间:2015-10-26 07:38:01

标签: android android-adapter android-recyclerview

我有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?获得类似内容

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

3 个答案:

答案 0 :(得分: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. 修改您发布的代码:
    2. 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();
      }
      

答案 1 :(得分:2)

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

答案 2 :(得分:-2)

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

我在片段中嵌套了RecyclerView。 &安培;每当我获得新数据(例如来自数据库)时,我都会通过attach来刷新片段的布局。 detach来自容器活动:

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

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

&安培;这样,您也可以刷新RecyclerView的布局。但你记住这一点:

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