解析NewsAPI的JSON数据后RecyclerView无内容显示问题求助
问题排查与修复方案
我帮你找出了代码里的几个核心问题,咱们一步步来解决:
核心问题分析
- JSON解析逻辑错误:你请求返回的JSON根节点是一个
JSONObject,里面包含articles数组,但你直接把整个响应当成JSONArray解析,这必然会抛出JSON异常。 - AsyncTask逻辑混乱:你在后台线程调用了
parseResult(UI操作不能在后台执行),而且doInBackground返回的result始终是null,导致onPostExecute里的解析完全无效。 - Adapter数据更新缺失:初始化时
modelList是null,即使后续解析出数据,Adapter也不知道数据变化,没有触发刷新。
分步修复代码
1. 修正JSON解析逻辑
把根节点当作JSONObject处理,取出里面的articles数组再解析:
private void parseResult(String result){ try { JSONObject rootObject = new JSONObject(result); JSONArray posts = rootObject.getJSONArray("articles"); // 取出真正的文章数组 modelList.clear(); // 先清空旧数据 for (int i=0;i<posts.length();i++){ JSONObject post = posts.optJSONObject(i); Model item = new Model(); item.setAuthor(post.optString("author")); item.setTitle(post.optString("title")); item.setDescription(post.optString("description")); // 可以按需添加其他字段,比如urlToImage、publishedAt等 modelList.add(item); Log.d("AuthorForJSON : ", post.optString("author")); } // 解析完成后通知Adapter刷新 customAdapter.notifyDataSetChanged(); } catch (JSONException e) { e.printStackTrace(); Toast.makeText(this, "数据解析失败", Toast.LENGTH_SHORT).show(); } }
2. 修复AsyncTask的执行逻辑
后台线程只负责获取网络响应,把解析操作放到onPostExecute(UI线程)中执行:
public class DownloadTask extends AsyncTask<String,Void,String> { private ProgressDialog progressDialog=new ProgressDialog(MainActivity.this); @Override protected void onPreExecute() { progressDialog.setMessage("Loading..."); progressDialog.setCancelable(false); progressDialog.show(); } @Override protected String doInBackground(String... strings) { StringBuilder response = new StringBuilder(); try { URL url = new URL(strings[0]); HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); int statusCode = urlConnection.getResponseCode(); if (statusCode == HttpsURLConnection.HTTP_OK) { BufferedReader br = new BufferedReader( new InputStreamReader(urlConnection.getInputStream())); String line; while ((line = br.readLine()) != null) { response.append(line); } } else { runOnUiThread(() -> Toast.makeText(getApplicationContext(), "请求失败,状态码:" + statusCode, Toast.LENGTH_LONG).show()); } } catch (MalformedURLException e) { e.printStackTrace(); runOnUiThread(() -> Toast.makeText(getApplicationContext(), "URL格式错误", Toast.LENGTH_LONG).show()); } catch (IOException e) { e.printStackTrace(); runOnUiThread(() -> Toast.makeText(getApplicationContext(), "网络异常", Toast.LENGTH_LONG).show()); } catch (Exception e) { e.printStackTrace(); runOnUiThread(() -> Toast.makeText(getApplicationContext(), "未知错误", Toast.LENGTH_LONG).show()); } Log.d("ResponseForParsing : ", response.toString()); return response.toString(); // 返回完整的响应字符串 } @Override protected void onPostExecute(String result) { super.onPostExecute(result); if (progressDialog != null && progressDialog.isShowing()) { progressDialog.dismiss(); } if (result != null && !result.isEmpty()) { parseResult(result); // 在UI线程解析数据 } else { Toast.makeText(getApplicationContext(), "未获取到有效数据", Toast.LENGTH_LONG).show(); } } }
3. 修正Adapter初始化与数据绑定
确保Adapter持有有效的空列表,并完善ViewHolder的绑定逻辑:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> { private Context context; private List<Model> modelList; public CustomAdapter(Context context, List<Model> modelList) { this.context = context; this.modelList = modelList != null ? modelList : new ArrayList<>(); // 避免null引用 } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { Model item = modelList.get(position); // 根据你的row布局控件ID修改 holder.authorTv.setText(item.getAuthor()); holder.titleTv.setText(item.getTitle()); holder.descTv.setText(item.getDescription()); } @Override public int getItemCount() { return modelList.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { TextView authorTv; TextView titleTv; TextView descTv; public ViewHolder(@NonNull View itemView) { super(itemView); authorTv = itemView.findViewById(R.id.author_text); titleTv = itemView.findViewById(R.id.title_text); descTv = itemView.findViewById(R.id.desc_text); } } }
4. 修正MainActivity的初始化逻辑
确保modelList初始化为空列表,避免Adapter持有null引用:
private List<Model> modelList = new ArrayList<>(); // 初始化为空列表 private CustomAdapter customAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = findViewById(R.id.list); recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); customAdapter = new CustomAdapter(MainActivity.this, modelList); recyclerView.setAdapter(customAdapter); recyclerView.setItemAnimator(new DefaultItemAnimator()); new DownloadTask().execute(url); }
额外注意事项
- 确保你的
Model类有对应的getter方法(比如getAuthor()、getTitle()),否则Adapter无法获取数据。 - 在
AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET" />。 - AsyncTask已被官方废弃,建议后续学习使用
Coroutines+OkHttp+ViewModel的组合来处理网络请求,更符合现代Android开发规范。
内容的提问来源于stack exchange,提问作者Pritom Mazumdar
相关产品推荐
相关产品推荐

