如何复用Firebase数据获取方法实现ListView按钮切换数据
按钮切换ListView数据的复用实现方案
问题背景
我有一个包含两个按钮和一个ListView的Fragment,需求如下:
- 点击
firstSemesterButton时,从Firebase获取course==1 && semester==1的科目数据,展示在ListView中 - 点击
secondSemesterButton时,从Firebase获取course==1 && semester==2的科目数据,替换ListView内容
目前已完成第一学期的查询逻辑,但需要复用现有方法和ListView实现数据切换。
解决方案
通过给数据查询方法添加学期参数实现复用,核心修改包括:
- 将单一学期的查询方法重构为带参数的通用方法
- 动态使用参数过滤数据库数据
- 管理Firebase监听避免重复回调和内存泄漏
修改后的完整代码
public class FirstCourseFragment extends Fragment implements View.OnClickListener { // 按钮相关 protected MaterialButtonToggleGroup toggleGroup; private Button firstSemesterButton, secondSemesterButton; private TextView semesterName; // Firebase相关 private DatabaseReference databaseReference; private static final String SUBJECT_KEY = "Subjects"; private ValueEventListener currentDbListener; // 保存当前监听引用 // ListView相关 private ListView listView; private ArrayAdapter<String> adapter; private List<String> listData; private List<Subject> listSubject; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_first_course, container, false); init(view); loadSemesterData(1); // 默认加载第一学期数据 setOnClickItem(); return view; } // 初始化控件与变量 private void init(View view) { semesterName = view.findViewById(R.id.nameSemesterFirstCourse); // ListView初始化 listView = view.findViewById(R.id.listFirstCourse); listData = new ArrayList<>(); listSubject = new ArrayList<>(); adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, listData); listView.setAdapter(adapter); // 按钮组初始化 toggleGroup = view.findViewById(R.id.toggleButtonGroup); firstSemesterButton = view.findViewById(R.id.firstSemesterButton); firstSemesterButton.setOnClickListener(this); secondSemesterButton = view.findViewById(R.id.secondSemesterButton); secondSemesterButton.setOnClickListener(this); // Firebase初始化 databaseReference = FirebaseDatabase.getInstance().getReference(SUBJECT_KEY); } // 通用学期数据加载方法,传入目标学期 private void loadSemesterData(final int targetSemester) { // 移除旧监听,避免重复回调 if (currentDbListener != null) { databaseReference.removeEventListener(currentDbListener); } currentDbListener = new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { // 清空现有数据 listData.clear(); listSubject.clear(); // 根据目标学期过滤数据 for (DataSnapshot ds : snapshot.getChildren()) { Subject subject = ds.getValue(Subject.class); if (subject != null && subject.course == 1 && subject.semester == targetSemester) { listData.add(subject.name); listSubject.add(subject); } } // 通知适配器更新UI adapter.notifyDataSetChanged(); } @Override public void onCancelled(@NonNull DatabaseError error) { // 可选:添加错误提示逻辑,如Toast.makeText(getActivity(), "数据加载失败", Toast.LENGTH_SHORT).show(); } }; databaseReference.addValueEventListener(currentDbListener); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.firstSemesterButton: semesterName.setText("First semester"); loadSemesterData(1); break; case R.id.secondSemesterButton: semesterName.setText("Second semester"); loadSemesterData(2); break; } } // ListView项点击跳转逻辑 private void setOnClickItem() { listView.setOnItemClickListener((parent, view, position, id) -> { Subject selectedSubject = listSubject.get(position); // 这里添加跳转逻辑,例如启动详情页面 // Intent intent = new Intent(getActivity(), SubjectDetailActivity.class); // intent.putExtra("subject", selectedSubject); // startActivity(intent); }); } @Override public void onDestroyView() { super.onDestroyView(); // 页面销毁时移除监听,防止内存泄漏 if (currentDbListener != null) { databaseReference.removeEventListener(currentDbListener); } } }
关键优化点
- 方法复用:通过
targetSemester参数实现同一方法适配不同学期查询,消除重复代码 - 监听管理:切换学期时移除旧监听,避免同一数据源多次回调导致数据异常
- 内存安全:在
onDestroyView中清理监听,防止Fragment销毁后仍持有Firebase引用造成内存泄漏 - 空安全:使用
if (subject != null)替代assert,提升代码稳定性 - 默认初始化:页面加载时默认展示第一学期数据,优化用户体验
内容的提问来源于stack exchange,提问作者AlexMo
相关产品推荐
相关产品推荐

