如何将两个适配器设置为一个 RecyclerView?

Posted

技术标签:

【中文标题】如何将两个适配器设置为一个 RecyclerView?【英文标题】:How to set two adapters to one RecyclerView? 【发布时间】:2017-04-02 16:51:15 【问题描述】:

我正在开发一个 android 应用程序,其中我在“FirebaseDatabase”上存储了两种不同类型的信息。

然后在MainActivity 中,我正在检索它们并在RecyclerView 中显示给用户。这两个信息都应该以不同的布局显示,即它们的布局不同,这就是为什么我有两个制作两个不同的模型类,现在有两个不同的适配器。我正在使用@MikePenz 的FastAdapter

所以,我所做的就是按照从数据库中获取信息的相同顺序在 recyclerview 上设置适配器:

1.

public void prepareDataOfSRequests() 
        gModelClass = new GModelClass(postedBy, ***, ***, ***, "error", ***, formattedTime, currentLatitude, currentLongitude, utcFormatDateTime, userEmail, userID, null, ***, itemID);
        fastItemAdapter.add(0, gModelClass);
        recyclerView.setAdapter(fastItemAdapter);
        recyclerView.smoothScrollToPosition(0);
        emptyRVtext.setVisibility(View.INVISIBLE);
    

2.

public void prepareDataOfERequests() 
        eModelClass = new EModelClass(***, ***, ***, ***, "error", ***, formattedTimeE, currentLatitudeE, currentLongitudeE, utcFormatDateTimeE, userEmailE, userIDE, null, ***, ***, ***, ***, itemID);
        fastItemAdapterER.add(eventRequestsModelClass);
        recyclerView.setAdapter(fastItemAdapterER);
        recyclerView.smoothScrollToPosition(0);
        emptyRVtext.setVisibility(View.INVISIBLE);
    

由于 recyclerview 只有一个,并且我正在逐个设置 2 个不同的适配器,因此 recyclerview 正在使用第二个适配器进行更新并仅显示其内容。

那么,如何将两个适配器显示或设置为相同的“RecyclerView”,并且可以显示存储在两个适配器中的内容。

【问题讨论】:

你可以做两种类型的viewholder并要求一个接口......如果项目是instanceOf class1,则绘制viewholder1,否则为viewholder2 @JCDecary 但我必须在回收站视图中显示它们。我认为您的代码将显示其中一个。对吗? 不,你将拥有两者,你只需要覆盖 getitemcount @JCDecary 哦,好吧...兄弟,你能不能写一些代码实际上我不是很专业,所以很难理解。如果您可以编写一些代码作为答案,那就太好了。请。 @Marcin Jedynak 比我快 【参考方案1】:

您不能在一个 RecyclerView 上设置两个适配器。但是,您可以制作一个处理两种类型项目的自定义适配器。方法如下:

假设您需要显示两种类型的对象A动物和Beverages。让我们处理最困难的情况,即您的对象需要完全不同的布局来显示它们,并且完全不同的ViewHolders。这里是ViewHolders

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> 
    ...
    private static class AnimalViewHolder extends RecyclerView.ViewHolder 
        public AnimalViewHolder(View itemView) 
            super(itemView);

            // prepare your ViewHolder
        

        public void bind(Animal animal) 
            // display your object
        
    

    private static class BeverageViewHolder extends RecyclerView.ViewHolder 
        // like the one above
        ...
    

首先向适配器添加代表视图类型的常量:

private static final int ITEM_TYPE_ANIMAL;
private static final int ITEM_TYPE_BEVERAGE;

为简单起见,假设您将对象存储在列表中:

private List<Object> items = new ArrayList<>();

public MyAdapter(List<Object> items) 
    this.items.addAll(items);
    ...

首先你需要实现getItemViewType:

@Override
public int getItemViewType(int position) 
    if (items.get(position) instanceof Animal) 
        return ITEM_TYPE_ANIMAL;
     else 
        return ITEM_TYPE_BEVERAGE;
    
 

接下来使用onCreateViewHolder中的项目类型:

@Override 
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)  
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());

    if (viewType == ITEM_TYPE_ANIMAL) 
        layoutInflater.inflate(R.layout.item_animal, parent, false);

        return new AnimalViewHolder(view);
     else       
        layoutInflater.inflate(R.layout.item_beverage, parent, false);

        return new BeverageViewHolder(view);
     
 

最后你绑定了正确的视图持有者:

@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) 
    Object item = items.get(position);

    if (viewHolder instanceof AnimalViewHolder) 
        ((AnimalViewHolder) viewHolder).bind((Animal) item);
     else 
        ((BeverageViewHolder) viewHolder).bind((Beverage) item);
     
 

【讨论】:

您可以在 getItemViewType 中返回您的布局资源 ID。然后在 onCreateViewHolder 中,只需在方法参数中膨胀 viewType 你可以,但是只有在两种布局都使用相同的 ViewHolder 时,这个技巧才能发挥其全部潜力。否则,您在创建和绑定中继续使用 if-else,并且收益微乎其微。【参考方案2】:

连接适配器

ConcatAdapter 是recyclerview:1.2.0-alpha02 中的一个新类 这使您能够顺序组合多个适配器 显示在单个 RecyclerView 中。这使您能够更好地 封装您的适配器,而不必组合许多数据 源到单个适配器中,使它们保持专注和可重用。

来源:https://medium.com/androiddevelopers/merge-adapters-sequentially-with-mergeadapter-294d2942127a

用法

val firstAdapter: FirstAdapter = …
val secondAdapter: SecondAdapter = …
val thirdAdapter: ThirdAdapter = …

val concatAdapter = ConcatAdapter(firstAdapter, secondAdapter, 
     thirdAdapter)
recyclerView.adapter = concatAdapter

【讨论】:

大声笑,它已重命名为ConcatAdapter【参考方案3】:

如果你愿意,你绝对可以写一个中间层来接受多个适配器。

如果你有兴趣,可以看看我是做什么的。 https://github.com/Jintin/MixAdapter

【讨论】:

以上是关于如何将两个适配器设置为一个 RecyclerView?的主要内容,如果未能解决你的问题,请参考以下文章

如何在视图中转换绑定?

如何翻译视图中的绑定?

如何在阵列适配器中长按时设置按钮的可见性

更改适配器中项目的视图

如何将图像视图的可见性设置为 Spinner 所选项目的可见性

如何将源 IP 地址设置为 0.0.0.0?