You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Retrofit按Type过滤JSON并在RecyclerView展示的实现方法

解决JSON解析、分类与RecyclerView绑定的三步方案

我来一步步帮你搞定这三个问题,都是Android开发里很常见的场景,咱们逐个击破:

1. 按Type字段解析JSON数组响应

首先注意到你的JSON里有个对象用了TenHangHoa而不是Name字段,所以得先调整你的Drink类,让它能兼容这两个字段。这里用Gson来解析的话,用@SerializedName的alternate参数就能轻松解决字段不一致的问题:

public class Drink {
    private String Id;
    // 同时识别JSON里的Name和TenHangHoa字段,映射到Name属性
    @SerializedName(value = "Name", alternate = {"TenHangHoa"})
    private String Name;
    private String Type;

    // 别忘了补上getter和setter
    public String getId() { return Id; }
    public void setId(String id) { Id = id; }
    public String getName() { return Name; }
    public void setName(String name) { Name = name; }
    public String getType() { return Type; }
    public void setType(String type) { Type = type; }
}

接下来解析JSON数组成List<Drink>:

// 假设你的接口返回的JSON字符串是jsonResponse
Gson gson = new Gson();
// 用TypeToken获取List<Drink>的泛型类型
Type drinkListType = new TypeToken<List<Drink>>(){}.getType();
List<Drink> drinkList = gson.fromJson(jsonResponse, drinkListType);

这样就把JSON数组完整解析成了Drink对象的列表,每个对象的Type字段也都正确赋值了。

2. 将解析后的数据按Type分类保存为列表

要按Type分类,用Map<String, List<Drink>>来存储最方便——键是Type值,值是对应类型的所有饮品:

Map<String, List<Drink>> categorizedDrinks = new HashMap<>();

for (Drink drink : drinkList) {
    String type = drink.getType();
    // 如果当前Type还没在Map里,先创建一个空列表
    if (!categorizedDrinks.containsKey(type)) {
        categorizedDrinks.put(type, new ArrayList<>());
    }
    // 把饮品添加到对应Type的列表中
    categorizedDrinks.get(type).add(drink);
}

如果要给RecyclerView做分组展示,还需要把这个Map转换成一个混合列表,交替存放分类标题和对应的饮品:

// 先创建一个Title类来标记分类标题
class Title {
    private String typeName;
    public Title(String typeName) { this.typeName = typeName; }
    public String getTypeName() { return typeName; }
}

// 构建用于展示的混合列表
List<Object> displayList = new ArrayList<>();
for (Map.Entry<String, List<Drink>> entry : categorizedDrinks.entrySet()) {
    // 添加分类标题
    displayList.add(new Title(entry.getKey()));
    // 添加该分类下的所有饮品
    displayList.addAll(entry.getValue());
}

这样displayList里就有了「标题+饮品项」的结构,完美适配分组展示的需求。

3. 将列表传入RecyclerView适配器并绑定

接下来要写一个支持多类型的RecyclerView适配器,因为我们的displayList里有Title和Drink两种类型:

public class DrinkAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    // 定义两种视图类型
    private static final int TYPE_TITLE = 0;
    private static final int TYPE_DRINK = 1;
    private List<Object> displayList;

    public DrinkAdapter(List<Object> displayList) {
        this.displayList = displayList;
    }

    // 判断当前项的视图类型
    @Override
    public int getItemViewType(int position) {
        return displayList.get(position) instanceof Title ? TYPE_TITLE : TYPE_DRINK;
    }

    // 创建对应的ViewHolder
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        if (viewType == TYPE_TITLE) {
            View titleView = inflater.inflate(R.layout.item_title, parent, false);
            return new TitleViewHolder(titleView);
        } else {
            View drinkView = inflater.inflate(R.layout.item_drink, parent, false);
            return new DrinkViewHolder(drinkView);
        }
    }

    // 绑定数据到ViewHolder
    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof TitleViewHolder) {
            Title title = (Title) displayList.get(position);
            ((TitleViewHolder) holder).titleTv.setText(title.getTypeName());
        } else if (holder instanceof DrinkViewHolder) {
            Drink drink = (Drink) displayList.get(position);
            ((DrinkViewHolder) holder).idTv.setText(drink.getId());
            ((DrinkViewHolder) holder).nameTv.setText(drink.getName());
        }
    }

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

    // 标题的ViewHolder
    static class TitleViewHolder extends RecyclerView.ViewHolder {
        TextView titleTv;
        public TitleViewHolder(@NonNull View itemView) {
            super(itemView);
            titleTv = itemView.findViewById(R.id.tv_title);
        }
    }

    // 饮品项的ViewHolder
    static class DrinkViewHolder extends RecyclerView.ViewHolder {
        TextView idTv;
        TextView nameTv;
        public DrinkViewHolder(@NonNull View itemView) {
            super(itemView);
            idTv = itemView.findViewById(R.id.tv_drink_id);
            nameTv = itemView.findViewById(R.id.tv_drink_name);
        }
    }
}

然后在你的Activity或Fragment里完成RecyclerView的绑定:

// 找到RecyclerView
RecyclerView recyclerView = findViewById(R.id.recycler_view);
// 设置布局管理器,这里用线性布局
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// 创建适配器并传入displayList
DrinkAdapter adapter = new DrinkAdapter(displayList);
recyclerView.setAdapter(adapter);

最后补上两个简单的布局文件:

  • item_title.xml(分类标题布局):
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tv_title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:textSize="18sp"
    android:textStyle="bold"
    android:background="#f5f5f5"/>
  • item_drink.xml(饮品项布局):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">
    <TextView
        android:id="@+id/tv_drink_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:textColor="#666"/>
    <TextView
        android:id="@+id/tv_drink_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginTop="4dp"/>
</LinearLayout>

这样一套流程走下来,就能完成JSON解析、分类和RecyclerView的分组展示啦!

内容的提问来源于stack exchange,提问作者膼膬ng Bùi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:57:17