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

Firebase跨节点数据下,如何实现ListView的权限过滤?

实现管理员端ListView按部门过滤紧急事件的方法

核心思路:先获取当前管理员的权限部门,匹配对应的紧急事件类型,再通过Firebase查询或本地过滤,只展示符合权限的事件数据。


方法一:Firebase实时查询过滤(推荐)

这种方式利用Firebase数据库的查询能力,直接从服务器获取过滤后的数据,适合实时场景,且节省客户端资源。

1. 获取当前管理员的权限部门

先通过Firebase Auth拿到当前登录管理员的UID,再从Admin Users节点读取其部门权限,确定允许查看的紧急事件类型:

String currentAdminUid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference adminRef = FirebaseDatabase.getInstance().getReference("Admin Users").child(currentAdminUid);

adminRef.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        if (snapshot.exists()) {
            String allowedEmergencyType = "";
            DataSnapshot deptSnapshot = snapshot.child("Department");
            
            // 匹配部门对应的紧急事件类型
            if (deptSnapshot.child("Police").getValue(Integer.class) == 1) {
                allowedEmergencyType = "Police Assistance";
            } else if (deptSnapshot.child("Hospital").getValue(Integer.class) == 1) {
                allowedEmergencyType = "Medical Assistance";
            } else if (deptSnapshot.child("Fire Dept").getValue(Integer.class) == 1) {
                allowedEmergencyType = "Fire Assistance";
            }

            // 初始化过滤后的ListView
            setupFilteredListView(allowedEmergencyType);
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {
        Log.e(TAG, "获取管理员权限失败: " + error.getMessage());
    }
});

2. 构建过滤查询并初始化适配器

将适配器逻辑封装到方法中,根据允许的事件类型构建Firebase Query:

private void setupFilteredListView(String allowedEmergencyType) {
    // 只查询emergencyType匹配的用户数据
    Query filteredQuery = FirebaseDatabase.getInstance().getReference("Users")
            .orderByChild("emergencyType")
            .equalTo(allowedEmergencyType);

    FirebaseListOptions<MainData> options = new FirebaseListOptions.Builder<MainData>()
            .setLayout(R.layout.location_item)
            .setQuery(filteredQuery, MainData.class)
            .build();

    // 初始化适配器(注意顺序:先初始化适配器,再设置给ListView)
    locationAdapter = new FirebaseListAdapter<MainData>(options) {
        @Override
        protected void populateView(@NonNull View v, @NonNull MainData model, int position) {
            // 保留原有的视图填充逻辑
            TextView emergencyTypeView = v.findViewById(R.id.emergencyText);
            TextView scenarioView = v.findViewById(R.id.ScenarioText);
            Button emergencyButton = v.findViewById(R.id.itemButton);
            
            emergencyTypeView.setText(model.getEmergencyType());
            scenarioView.setText(model.getScenario());
            String selectedUid = getRef(position).getKey();

            // 保留原有的按钮点击逻辑
            emergencyButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    assert selectedUid != null;
                    DatabaseReference selectedUserLocationRef = FirebaseDatabase.getInstance()
                            .getReference().child("User Location").child(selectedUid);

                    selectedUserLocationRef.addListenerForSingleValueEvent(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot locationSnapshot) {
                            if (locationSnapshot.exists()) {
                                Double latitude = locationSnapshot.child("latitude").getValue(Double.class);
                                Double longitude = locationSnapshot.child("longitude").getValue(Double.class);

                                if (latitude != null && longitude != null) {
                                    Intent intent = new Intent(LocationLog.this, EmergencyDetails.class);
                                    intent.putExtra("Emergency Type", model.getEmergencyType());
                                    intent.putExtra("Scenario", model.getScenario());
                                    intent.putExtra("Latitude", latitude);
                                    intent.putExtra("Longitude", longitude);
                                    startActivity(intent);
                                } else {
                                    Log.e(TAG, "Latitude or Longitude is null");
                                }
                            } else {
                                Log.e(TAG, "Location data does not exist for UID: " + selectedUid);
                            }
                        }

                        @Override
                        public void onCancelled(@NonNull DatabaseError locationError) {
                            Log.e(TAG, "Location data retrieval error: " + locationError.getMessage());
                        }
                    });
                }
            });

            Log.d(TAG, "Emergency Type: " + model.getEmergencyType());
        }
    };

    // 绑定适配器到ListView
    locationList.setAdapter(locationAdapter);
}

3. 修复原代码的顺序问题

原代码中locationList.setAdapter(locationAdapter)写在适配器初始化之前,会导致空指针异常,上面的代码已经调整了顺序:先初始化适配器,再绑定到ListView。


方法二:本地过滤(适合特殊场景)

如果无法使用Firebase查询过滤(比如复杂多条件场景),可以先加载所有数据,再在客户端本地过滤:

// 先获取管理员权限对应的事件类型(同方法一的步骤1)
String allowedEmergencyType = "Police Assistance"; // 示例值,实际从管理员节点获取

DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("Users");
usersRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        List<MainData> filteredList = new ArrayList<>();
        for (DataSnapshot userSnapshot : snapshot.getChildren()) {
            MainData data = userSnapshot.getValue(MainData.class);
            if (data != null && data.getEmergencyType().equals(allowedEmergencyType)) {
                filteredList.add(data);
            }
        }
        // 使用普通ArrayAdapter加载过滤后的列表
        ArrayAdapter<MainData> adapter = new ArrayAdapter<>(LocationLog.this, R.layout.location_item, filteredList);
        locationList.setAdapter(adapter);
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {
        Log.e(TAG, "加载用户数据失败: " + error.getMessage());
    }
});

关键注意事项

  • 确保MainData类的字段与数据库键完全匹配(比如emergencyType对应数据库的emergencyType),否则Firebase无法正确解析数据。
  • 通过Firebase规则限制Admin Users节点的写权限,防止管理员篡改自己的部门权限。
  • 方法一支持实时数据更新,方法二需要手动处理数据变化。

内容的提问来源于stack exchange,提问作者Rafael Campos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 02:43:15