如何在RecyclerView双视图中解析多JSON数据?父Bean类解析遇困
嘿,我来帮你搞定这个RecyclerView多布局+父Bean类解析子Bean的问题!
解决RecyclerView多布局+父Bean类解析子Bean的问题
第一步:定义父类和子类Bean
首先我们需要创建一个父类作为所有Item的基类,让两个子Bean继承它,同时加上类型标识来区分不同数据类型:
// 父Bean类,作为所有传感器Item的基类 public abstract class BaseSensorItem { // 从JSON中获取的类型标识字段,用来区分不同子Bean public String type; // 抽象方法,统一返回布局类型标识 public abstract int getItemType(); } // 第一个子Bean:温度传感器数据 public class TemperatureSensor extends BaseSensorItem { public String temperature; public String unit; @Override public int getItemType() { return 0; // 标记为温度类型布局 } } // 第二个子Bean:湿度传感器数据 public class HumiditySensor extends BaseSensorItem { public String humidity; public String range; @Override public int getItemType() { return 1; // 标记为湿度类型布局 } }
第二步:自定义JSON解析器(以Gson为例)
我们可以用Gson的自定义TypeAdapter,根据JSON里的type字段自动解析成对应的子类:
public class BaseSensorItemAdapter extends TypeAdapter<BaseSensorItem> { private final Gson gson = new Gson(); @Override public void write(JsonWriter out, BaseSensorItem value) throws IOException { gson.toJson(value, value.getClass(), out); } @Override public BaseSensorItem read(JsonReader in) throws IOException { JsonObject jsonObject = gson.fromJson(in, JsonObject.class); String itemType = jsonObject.get("type").getAsString(); // 根据type字段判断解析成对应子类 if ("temperature".equals(itemType)) { return gson.fromJson(jsonObject, TemperatureSensor.class); } else if ("humidity".equals(itemType)) { return gson.fromJson(jsonObject, HumiditySensor.class); } // 后续扩展其他类型可在这里添加判断 return null; } }
解析JSON时这样使用:
// 初始化带自定义解析器的Gson实例 Gson gson = new GsonBuilder() .registerTypeAdapter(BaseSensorItem.class, new BaseSensorItemAdapter()) .create(); // 把JSON数组解析成BaseSensorItem列表 List<BaseSensorItem> sensorList = Arrays.asList(gson.fromJson(yourJsonString, BaseSensorItem[].class));
第三步:实现RecyclerView多布局Adapter
接下来编写Adapter,通过getItemViewType区分布局,绑定对应的数据:
public class SensorAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private List<BaseSensorItem> mSensorData; // 布局ID常量 private static final int LAYOUT_TEMPERATURE = R.layout.item_temperature; private static final int LAYOUT_HUMIDITY = R.layout.item_humidity; public SensorAdapter(List<BaseSensorItem> data) { mSensorData = data; } @Override public int getItemViewType(int position) { // 返回当前Item对应的布局类型标识 return mSensorData.get(position).getItemType(); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); View view; if (viewType == 0) { view = inflater.inflate(LAYOUT_TEMPERATURE, parent, false); return new TemperatureViewHolder(view); } else { view = inflater.inflate(LAYOUT_HUMIDITY, parent, false); return new HumidityViewHolder(view); } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { BaseSensorItem item = mSensorData.get(position); // 根据ViewHolder类型绑定对应数据 if (holder instanceof TemperatureViewHolder) { TemperatureSensor tempItem = (TemperatureSensor) item; ((TemperatureViewHolder) holder).tvTemp.setText(tempItem.temperature); ((TemperatureViewHolder) holder).tvUnit.setText(tempItem.unit); } else if (holder instanceof HumidityViewHolder) { HumiditySensor humiItem = (HumiditySensor) item; ((HumidityViewHolder) holder).tvHumidity.setText(humiItem.humidity); ((HumidityViewHolder) holder).tvRange.setText(humiItem.range); } } @Override public int getItemCount() { return mSensorData.size(); } // 温度传感器ViewHolder static class TemperatureViewHolder extends RecyclerView.ViewHolder { TextView tvTemp; TextView tvUnit; public TemperatureViewHolder(View itemView) { super(itemView); tvTemp = itemView.findViewById(R.id.tv_temperature); tvUnit = itemView.findViewById(R.id.tv_unit); } } // 湿度传感器ViewHolder static class HumidityViewHolder extends RecyclerView.ViewHolder { TextView tvHumidity; TextView tvRange; public HumidityViewHolder(View itemView) { super(itemView); tvHumidity = itemView.findViewById(R.id.tv_humidity); tvRange = itemView.findViewById(R.id.tv_range); } } }
第四步:在SensorFragment中整合使用
最后回到你的Fragment,初始化RecyclerView并绑定数据:
public class SensorFragment extends Fragment { private static final String ARG_PARAM1 = "param1"; private static final String ARG_PARAM2 = "param2"; private String mParam1; private String mParam2; private RecyclerView mRecyclerView; private SensorAdapter mAdapter; private List<BaseSensorItem> mSensorList = new ArrayList<>(); public static SensorFragment newInstance(String param1, String param2) { SensorFragment fragment = new SensorFragment(); Bundle args = new Bundle(); args.putString(ARG_PARAM1, param1); args.putString(ARG_PARAM2, param2); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mParam1 = getArguments().getString(ARG_PARAM1); mParam2 = getArguments().getString(ARG_PARAM2); } // 这里可以调用接口获取JSON数据,然后解析到mSensorList // parseJson(yourJsonResponse); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_sensor, container, false); mRecyclerView = view.findViewById(R.id.recycler_sensor); mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); mAdapter = new SensorAdapter(mSensorList); mRecyclerView.setAdapter(mAdapter); return view; } // 解析JSON数据的方法 private void parseJson(String jsonData) { Gson gson = new GsonBuilder() .registerTypeAdapter(BaseSensorItem.class, new BaseSensorItemAdapter()) .create(); BaseSensorItem[] items = gson.fromJson(jsonData, BaseSensorItem[].class); mSensorList.addAll(Arrays.asList(items)); mAdapter.notifyDataSetChanged(); } }
关键要点总结
- 父Bean类需要包含类型标识字段,用来区分不同子Bean;
- JSON解析时通过自定义TypeAdapter,根据类型字段动态匹配子类;
- RecyclerView Adapter通过
getItemViewType返回对应布局ID,创建不同ViewHolder绑定数据。
这样就能完美实现单个RecyclerView加载两种布局,同时解决JSON解析的问题啦!
内容的提问来源于stack exchange,提问作者Subhash Pandey
相关产品推荐
相关产品推荐

