Android Studio RecyclerView报错:No adapter attached; skipping layout 求助
解决RecyclerView无内容显示及"No adapter attached"警告问题
问题根源
出现W/RecyclerView: No adapter attached; skipping layout警告的核心原因:
- RecyclerView未设置LayoutManager(你的代码中这部分被注释)
- 完全未实现RecyclerView的Adapter,无数据绑定逻辑
- 仅完成Firebase数据写入,缺少读取数据并更新UI的代码
分步解决方案
1. 启用RecyclerView的LayoutManager
在MainActivity的onCreate方法中,添加LayoutManager初始化代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // ... 其他初始化代码 ... recyclerView = findViewById(R.id.recycle_view); // 必选:设置布局管理器,RecyclerView才能确定Item排列方式 recyclerView.setLayoutManager(new LinearLayoutManager(this)); // ... 其他代码 ... }
2. 创建RecyclerView的Item布局(res/layout/item_expense.xml)
创建单条消费记录的展示布局:
<?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:background="#fff"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:justifyContent="space-between"> <TextView android:id="@+id/tv_category" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:textStyle="bold" android:textColor="#000"/> <TextView android:id="@+id/tv_amount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:textColor="#ff0000"/> </LinearLayout> <TextView android:id="@+id/tv_note" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="14sp" android:textColor="#666" android:layout_marginTop="4dp"/> <TextView android:id="@+id/tv_date" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="12sp" android:textColor="#999" android:layout_marginTop="4dp" android:gravity="end"/> </LinearLayout> </androidx.cardview.widget.CardView>
3. 创建RecyclerView的Adapter类(ExpenseAdapter.java)
实现Adapter绑定数据到Item布局:
package my.edu.utar.practicalassignment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import java.util.List; public class ExpenseAdapter extends RecyclerView.Adapter<ExpenseAdapter.ExpenseViewHolder> { private List<Data> expenseList; public ExpenseAdapter(List<Data> expenseList) { this.expenseList = expenseList; } @NonNull @Override public ExpenseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_expense, parent, false); return new ExpenseViewHolder(view); } @Override public void onBindViewHolder(@NonNull ExpenseViewHolder holder, int position) { Data expense = expenseList.get(position); holder.tvCategory.setText(expense.getCategory()); holder.tvAmount.setText("RM " + expense.getAmount()); holder.tvNote.setText(expense.getNotes()); holder.tvDate.setText(expense.getDate()); } @Override public int getItemCount() { return expenseList.size(); } // 更新数据并通知UI刷新 public void updateData(List<Data> newList) { expenseList = newList; notifyDataSetChanged(); } public static class ExpenseViewHolder extends RecyclerView.ViewHolder { TextView tvCategory, tvAmount, tvNote, tvDate; public ExpenseViewHolder(@NonNull View itemView) { super(itemView); tvCategory = itemView.findViewById(R.id.tv_category); tvAmount = itemView.findViewById(R.id.tv_amount); tvNote = itemView.findViewById(R.id.tv_note); tvDate = itemView.findViewById(R.id.tv_date); } } }
4. 在MainActivity中初始化Adapter并添加Firebase数据监听
修改MainActivity,添加数据列表、Adapter实例,并监听Firebase数据变化:
// 在MainActivity成员变量中添加: private List<Data> expenseList = new ArrayList<>(); private ExpenseAdapter expenseAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // ... 其他初始化代码 ... recyclerView = findViewById(R.id.recycle_view); recyclerView.setLayoutManager(new LinearLayoutManager(this)); // 初始化Adapter并绑定到RecyclerView expenseAdapter = new ExpenseAdapter(expenseList); recyclerView.setAdapter(expenseAdapter); // ... 其他代码 ... // 添加Firebase数据监听,实时获取消费记录 ref.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { expenseList.clear(); for (DataSnapshot dataSnapshot : snapshot.getChildren()) { Data expense = dataSnapshot.getValue(Data.class); expenseList.add(expense); } expenseAdapter.updateData(expenseList); } @Override public void onCancelled(@NonNull DatabaseError error) { Toast.makeText(MainActivity.this, "数据读取失败: " + error.getMessage(), Toast.LENGTH_SHORT).show(); } }); }
5. 补充Data类的Getter方法
确保Data类有对应的getter方法,Adapter需要通过这些方法获取数据:
public class Data { private String category; private String date; private String id; private String notes; private int amount; // 空构造方法(Firebase序列化必须) public Data() {} public Data(String category, String date, String id, String notes, int amount) { this.category = category; this.date = date; this.id = id; this.notes = notes; this.amount = amount; } // 添加Getter方法 public String getCategory() { return category; } public String getDate() { return date; } public String getId() { return id; } public String getNotes() { return notes; } public int getAmount() { return amount; } }
6. 优化RecyclerView高度设置
在activity_main.xml中,将RecyclerView的固定高度556dp改为match_parent,适配不同屏幕:
<androidx.recyclerview.widget.RecyclerView android:id="@+id/recycle_view" android:layout_width="match_parent" android:layout_height="match_parent" />
验证效果
完成修改后重新运行App:
- 添加消费记录后,数据会实时写入Firebase并显示在RecyclerView中
- 不再出现"No adapter attached"警告
内容的提问来源于stack exchange,提问作者Coding Rookie
相关产品推荐
相关产品推荐

