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

从Assets解析JSON到RecyclerView触发空指针异常的排查与修复

Fixing NullPointerException & JSON Parsing Issues with RecyclerView

Let's break down your problem and walk through a complete fix step by step, like we're troubleshooting together:

1. Fix the Immediate Layout Loading Bug

You already spotted this critical issue, but let's cement the fix: your JSONSearchItemAdapter was inflating the activity layout (R.layout.search_activity) instead of the single item layout in onCreateViewHolder. This is exactly why you got that NullPointerException in onBindViewHolder—the adapter couldn't find the TextView elements that only exist in your item layout.

Update your adapter's onCreateViewHolder method:

@NonNull
@Override
public StationViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    // Replace R.layout.search_activity with your actual item layout (e.g., R.layout.search_list_item)
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.search_list_item, parent, false);
    return new StationViewHolder(itemView);
}

2. Validate & Fix JSON Parsing with Gson

Even though your JSON has valid data, the "JSONArray is empty" log points to a mismatch between your parsing logic and the actual JSON structure. Let's build a robust Gson-based parsing flow:

Step 2.1: Define Your Data Classes

First, create classes that mirror your JSON structure perfectly. For example, if your asset1.json looks like this:

{
  "stations": [
    {"name": "Central Station", "id": "ST001"},
    {"name": "Downtown Station", "id": "ST002"}
  ]
}

Create these classes:

// Top-level response class matching the JSON root
public class StationResponse {
    // Field name must exactly match the JSON key (case-sensitive!)
    private List<Station> stations;

    public List<Station> getStations() {
        return stations;
    }
}

// Data class for individual station items
public class Station {
    private String name;
    private String id;

    // Getters are required for Gson to populate data
    public String getName() {
        return name;
    }

    public String getId() {
        return id;
    }
}

If your JSON uses different field names (e.g., station_name instead of name), use @SerializedName to map them: @SerializedName("station_name") private String name;

Step 2.2: Load & Parse JSON from Assets

Update your JSONSearchActivity code to safely read and parse the JSON file:

private void loadStationsAndPopulateRecyclerView() {
    try {
        // Read JSON file from assets
        InputStream inputStream = getAssets().open("asset1.json");
        int fileSize = inputStream.available();
        byte[] buffer = new byte[fileSize];
        inputStream.read(buffer);
        inputStream.close();
        String jsonString = new String(buffer, StandardCharsets.UTF_8);

        // Parse with Gson
        Gson gson = new Gson();
        StationResponse response = gson.fromJson(jsonString, StationResponse.class);
        List<Station> stationList = response.getStations();

        // Guard against null list to avoid crashes
        if (stationList == null) {
            stationList = new ArrayList<>();
            Toast.makeText(this, "No stations found in JSON", Toast.LENGTH_SHORT).show();
        }

        // Set up RecyclerView
        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(new JSONSearchItemAdapter(stationList));

    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(this, "Failed to load JSON file", Toast.LENGTH_SHORT).show();
    }
}

3. Finalize the Adapter Implementation

Make sure your adapter handles null lists correctly and binds views properly:

public class JSONSearchItemAdapter extends RecyclerView.Adapter<JSONSearchItemAdapter.StationViewHolder> {

    private List<Station> stationList;

    // Constructor with null safety to prevent unexpected crashes
    public JSONSearchItemAdapter(List<Station> stationList) {
        this.stationList = stationList != null ? stationList : new ArrayList<>();
    }

    @NonNull
    @Override
    public StationViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.search_list_item, parent, false);
        return new StationViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull StationViewHolder holder, int position) {
        Station station = stationList.get(position);
        // Bind data to views (ensure IDs match your item layout XML exactly!)
        holder.stationName.setText(station.getName());
        holder.stationId.setText(station.getId());
    }

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

    // ViewHolder class with references to your item layout views
    static class StationViewHolder extends RecyclerView.ViewHolder {
        TextView stationName;
        TextView stationId;

        public StationViewHolder(@NonNull View itemView) {
            super(itemView);
            // Match these IDs to the ones in your item layout XML
            stationName = itemView.findViewById(R.id.tv_station_name);
            stationId = itemView.findViewById(R.id.tv_station_id);
        }
    }
}

4. Troubleshooting the "JSONArray is empty" Log

If you still see this log after fixing the above:

  • Print the raw jsonString to Logcat to confirm the file is being read correctly: Log.d("JSON_DEBUG", jsonString);
  • Double-check that your StationResponse class's field name exactly matches the array key in your JSON (case-sensitive!)
  • Ensure your asset file is placed in the src/main/assets directory (not a flavor-specific assets folder unless you're using product flavors)

内容的提问来源于stack exchange,提问作者AShX

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:22:47