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
相关产品推荐
相关产品推荐

