使用addValueEventListener()时出现Firebase Database权限拒绝错误
Firebase数据加载问题:addValueEventListener无响应且权限被拒
问题场景
我正在使用Firebase获取数据并加载到包含列表的Fragment中,计划通过自定义适配器(接收三个ArrayList作为输入)来构建列表。目前代码能成功将Firebase中存储的dates键文本设置到按钮上,说明连接没有问题,但addValueEventListener的代码完全不生效——ArrayList没有添加数据,回调里的Toast消息也没显示,同时出现以下错误:
Listen at /Attendance/1/A/1 failed: DatabaseError: Permission denied
相关代码
AttendanceFragment 代码
public class AttendanceFragment extends Fragment { private DatabaseReference reference, attendance, classid, divisionid, studentid, dates; private Button attbutton; private ListView list; private View mainview; private Activity activity; private ArrayList<String> date = new ArrayList<String>(), state = new ArrayList<String>(), teacher = new ArrayList<String>(); private ListAdapter listAdapter; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_attendence,container,false); } @Override public void onStart(){ super.onStart(); mainview = this.getView(); activity = this.getActivity(); attbutton = mainview.findViewById(R.id.att_per); list = mainview.findViewById(R.id.att_main_list); reference = FirebaseDatabase.getInstance().getReference(); attendance = reference.child(KeyStrings.attendance); classid = attendance.child(KeyStrings.class1); divisionid = classid.child(KeyStrings.division1); studentid = divisionid.child(KeyStrings.student1); dates = studentid.child("2018-07-06"); attbutton.setText(dates.getKey()); studentid.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Toast.makeText(activity, "Does it work?", Toast.LENGTH_LONG).show(); for(DataSnapshot d1: dataSnapshot.getChildren()){ date.add(d1.getKey()); state.add(d1.child(KeyStrings.att_status).getValue().toString()); teacher.add(d1.child(KeyStrings.att_created_by).getValue().toString()); } listAdapter = new AttendanceAdapter(activity, date, state, teacher); list.setAdapter(listAdapter); } @Override public void onCancelled(DatabaseError databaseError) { } }); } }
AttendanceAdapter 代码
public class AttendanceAdapter extends ArrayAdapter<String>{ private ArrayList<String> date; private ArrayList<String> state; private ArrayList<String> teacher; private Activity context; public AttendanceAdapter(Activity context, ArrayList<String>date, ArrayList<String>state, ArrayList<String>teacher) { super(context, R.layout.fragment_attendence, date); this.date=date; this.state=state; this.teacher=teacher; } @Override public View getView(int position, View convertView, ViewGroup parent){ LayoutInflater inflater = context.getLayoutInflater(); View listviewItem = inflater.inflate(R.layout.fragment_attendence,null,true); TextView dateview=(TextView)listviewItem.findViewById(R.id.att_list_date); TextView stateview=(TextView)listviewItem.findViewById(R.id.att_list_stat); TextView teacherview=(TextView)listviewItem.findViewById(R.id.att_list_teacher); dateview.setText(date.get(position)); stateview.setText(state.get(position)); teacherview.setText(teacher.get(position)); return listviewItem; } }
补充信息(编辑1)
我原本以为是Firebase权限或认证问题,附上当前的实时数据库规则:
{ "rules": { ".read": true, ".write": true } }
问题分析与解决方案
嘿,我来帮你捋捋这个问题的关键点~
1. 先解决核心的权限拒绝问题
虽然你贴了全开放的规则,但还是出现Permission denied,可以从这几个方向排查:
- 规则是否真的同步生效?:修改Firebase规则后,有时候需要等待1-2分钟才能全局同步,你可以试试重启模拟器/测试设备,或者在Firebase控制台重新发布一次规则。
- 数据库路径是否匹配?:错误里的路径是
/Attendance/1/A/1,你可以直接在Firebase实时数据库控制台手动访问这个路径,看看节点是否存在、拼写是否正确(比如大小写、节点名称有没有打错)。如果路径不存在,也可能触发权限错误。 - 是否混淆了数据库服务?:确认你修改的是实时数据库的规则,而不是Firestore的——这两个是完全独立的服务,规则不通用。
- 认证状态缓存问题:如果你的App启用了Firebase Auth,本地缓存的认证状态可能异常。可以在代码里打印当前用户状态排查:
要是未登录状态却读不到,试试清除App数据后重新测试。FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); Log.d("AuthCheck", user == null ? "未登录" : "当前用户ID:" + user.getUid());
2. 代码逻辑的优化点
就算权限问题解决了,你的代码还有几个小坑需要修正:
- Fragment获取View的方式:建议在
onCreateView里直接保存View实例,避免onStart时getView()返回null的情况:private View mainview; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { mainview = inflater.inflate(R.layout.fragment_attendence,container,false); return mainview; } - 适配器布局错误:你在适配器的构造方法和
getView里都用了fragment_attendence(Fragment的布局),这会导致列表项布局嵌套混乱。应该创建单独的列表项布局(比如attendance_list_item.xml),然后在适配器里引用这个布局。 - 数据重复累加问题:
addValueEventListener会在数据变化时重复触发,每次回调前要先清空三个ArrayList,不然数据会重复添加:@Override public void onDataChange(DataSnapshot dataSnapshot) { Toast.makeText(activity, "Does it work?", Toast.LENGTH_LONG).show(); // 先清空列表 date.clear(); state.clear(); teacher.clear(); for(DataSnapshot d1: dataSnapshot.getChildren()){ date.add(d1.getKey()); state.add(d1.child(KeyStrings.att_status).getValue().toString()); teacher.add(d1.child(KeyStrings.att_created_by).getValue().toString()); } // 不用重新创建适配器,直接通知数据变化即可 if(listAdapter == null){ listAdapter = new AttendanceAdapter(activity, date, state, teacher); list.setAdapter(listAdapter); } else { listAdapter.notifyDataSetChanged(); } }
内容的提问来源于stack exchange,提问作者Mihir Tanksale
相关产品推荐
相关产品推荐

