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

Android Studio RecyclerView报错:No adapter attached; skipping layout 求助

解决RecyclerView无内容显示及"No adapter attached"警告问题

问题根源

出现W/RecyclerView: No adapter attached; skipping layout警告的核心原因:

  1. RecyclerView未设置LayoutManager(你的代码中这部分被注释)
  2. 完全未实现RecyclerView的Adapter,无数据绑定逻辑
  3. 仅完成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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 19:18:39