从Assets解析JSON到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
jsonStringto Logcat to confirm the file is being read correctly:Log.d("JSON_DEBUG", jsonString); - Double-check that your
StationResponseclass's field name exactly matches the array key in your JSON (case-sensitive!) - Ensure your asset file is placed in the
src/main/assetsdirectory (not a flavor-specific assets folder unless you're using product flavors)
内容的提问来源于stack exchange,提问作者AShX

