Volley+Picasso解析JSON后RecyclerView无显示,报“No adapter attached”错误
问题排查与解决方案
嘿,我帮你梳理了下问题,你遇到的No adapter attached : skipping layout警告以及界面无内容显示,其实是由几个代码逻辑错误和初始化顺序问题导致的,我会一步步给你修复:
核心问题点梳理
- RecyclerView初始化时未绑定适配器:你在Volley异步请求回调里才设置适配器,而布局绘制时RecyclerView还没拿到适配器,就会抛出那个警告
- UserInfo类的getter/setter完全混乱:这会导致你传递的名称和图片路径完全错位,数据根本没法正确显示
- Adapter中控件ID查找错误:布局里的ImageButton是
imagebtn,但你在Adapter里找的是image,导致图片加载失败 - MainActivity错误查找子项控件:你直接在Activity里找CardView里的控件,这些控件属于RecyclerView的子项,应该由Adapter的ViewHolder来管理
- JSON解析时图片路径拼接错误:你把字段名和图片名拼在一起了,导致取到错误的字段值
- Toast未调用show():异常提示根本弹不出来,你没法及时发现解析错误
具体修复步骤
1. 彻底修复UserInfo类的逻辑
你的UserInfo类的getName()返回的是image_link,setName()设置的也是image_link,完全搞反了,这是最致命的错误,修改后如下:
public class UserInfo { private String name; private String imageLink; // 构造方法要和属性对应,你之前的构造参数也错了 public UserInfo(String name, String imageLink) { this.name = name; this.imageLink = imageLink; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getImageLink() { return imageLink; } public void setImageLink(String imageLink) { this.imageLink = imageLink; } }
2. 修正MainActivity的初始化逻辑
(1)删除错误的控件查找代码
你在Activity里找imagebtn和description是完全错误的,这些属于RecyclerView的子项布局,删除这两行:
// 删掉这两行! imageButton = findViewById(R.id.imagebtn); textView = findViewById(R.id.description);
(2)提前设置空适配器解决警告
在RecyclerView初始化时就绑定一个空适配器,避免布局绘制时无适配器的警告:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); progressbar = findViewById(R.id.progressBar); progressbar.setVisibility(View.VISIBLE); mRecyclerview = findViewById(R.id.recycler_view); mRecyclerview.setHasFixedSize(true); mRecyclerview.setLayoutManager(new LinearLayoutManager(this)); mExampleList = new ArrayList<>(); // 提前初始化适配器并绑定,解决No adapter警告 mExampleAdapter = new ExampleAdapter(MainActivity.this, mExampleList); mRecyclerview.setAdapter(mExampleAdapter); mExampleAdapter.setOnItemClickListener(MainActivity.this); mRequestQueue = Volley.newRequestQueue(this); jsonParse(); }
(3)修正JSON解析的图片路径
你之前的代码把字段名和图片名拼在一起了,导致取的字段是logo_pathcivil.png,这肯定不对,修改成正确的路径拼接:
// 原错误代码: // String image = obj.getString("logo_path" + "civil.png"); // 修改为(假设接口返回的logo_path是路径前缀,比如"http://xelwel.com.np/hamrosewaapp/uploads/images/logo/"): String logoPath = obj.getString("logo_path"); // 拼接完整图片路径 String image = logoPath + "civil.png"; // 如果接口返回的logo_path已经是完整图片地址,直接取就行: // String image = obj.getString("logo_path");
(4)更新数据后通知Adapter
在JSON解析完成后,不需要重新创建Adapter,直接更新数据并通知Adapter刷新:
try { JSONObject jsonObject = new JSONObject(response); JSONArray jsonArray = jsonObject.getJSONArray("org_list"); // 先清空列表,避免重复加载数据 mExampleList.clear(); for (int i = 0; i < jsonArray.length(); i++) { JSONObject obj = jsonArray.getJSONObject(i); String hsname = obj.getString("orga_organame"); String logoPath = obj.getString("logo_path"); String image = logoPath + "civil.png"; mExampleList.add(new UserInfo(hsname, image)); } // 通知Adapter数据更新 mExampleAdapter.notifyDataSetChanged(); progressbar.setVisibility(View.GONE); } catch (JSONException e) { // 修复Toast,加上show() Toast.makeText(getApplicationContext(),"Error Parsing Data", Toast.LENGTH_LONG).show(); e.printStackTrace(); }catch (Exception e) { Toast.makeText(getApplicationContext(),"Something went wrong", Toast.LENGTH_LONG).show(); e.printStackTrace(); }
3. 修复ExampleAdapter的控件查找错误
你的Adapter里ViewHolder找的ImageView ID是image,但布局里的ImageButton ID是imagebtn,导致控件为null,修改如下:
public class ViewHolder extends RecyclerView.ViewHolder { public TextView textView; public ImageButton imageView; // 注意这里是ImageButton,和布局一致 public ViewHolder(View itemView) { super(itemView); textView = itemView.findViewById(R.id.description); // 修正ID为imagebtn imageView = itemView.findViewById(R.id.imagebtn); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(mListener!= null){ int position = getAdapterPosition(); if (position!= RecyclerView.NO_POSITION){ mListener.onItemClick(position); } } } }); } }
同时,onBindViewHolder里的图片加载也要对应:
@Override public void onBindViewHolder(ViewHolder holder, int position) { UserInfo info = mExampleList.get(position); String imageUrl = info.getImageLink(); String hsname = info.getName(); holder.textView.setText(hsname); Picasso.with(mcontext).load(imageUrl).fit().centerInside().into(holder.imageView); }
4. 确保添加网络权限
检查你的AndroidManifest.xml里有没有添加网络权限,没有的话加上:
<uses-permission android:name="android.permission.INTERNET" />
完成以上所有修改后,你的RecyclerView应该能正常加载并显示数据,No adapter attached的警告也会消失,图片和文字都能正确显示啦!
内容的提问来源于stack exchange,提问作者Ayush Katuwal
相关产品推荐
相关产品推荐

