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

如何复用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 23:45:05