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

Java类间ArrayList共享:如何在两个Fragment间传递Firebase读取的列表数据

问题原因

你遇到的空指针报错是因为第二个Fragment里声明的Dashboard db变量没有赋值,直接调用方法自然会抛出空引用异常。除此之外你还会遇到第二个问题:Firebase的addValueEventListener是异步回调,就算你拿到了Dashboard实例,也可能出现调用TrasactionExpenses()时数据还没从Firebase加载完成,返回空列表的情况。

推荐解决方案

方案1:使用共享ViewModel(官方推荐Fragment间共享数据的方式)

这是Android Jetpack推荐的同Activity下Fragment共享数据的方案,不需要互相持有实例,也不用处理生命周期问题:

  1. 先创建共享的ViewModel类
public class SharedViewModel extends ViewModel {
    // 用MutableLiveData包裹列表可以监听数据变化,解决Firebase异步问题
    private final MutableLiveData<List<Catergory_List>> catList = new MutableLiveData<>(new ArrayList<>());

    public void setCatList(List<Catergory_List> list) {
        catList.setValue(list);
    }

    public LiveData<List<Catergory_List>> getCatList() {
        return catList;
    }
}
  1. 在Dashboard Fragment中加载完数据后更新ViewModel
// 先在Dashboard里初始化ViewModel,注意ViewModelProvider要传宿主Activity
private SharedViewModel sharedViewModel;

// 在onViewCreated生命周期中初始化
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);

private void GetCategory() {
    DatabaseReference db = FirebaseDatabase.getInstance().getReference("Category");
    db.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            List<Catergory_List> tempList = new ArrayList<>();
            for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
                Catergory_List cl = userSnapshot.getValue(Catergory_List.class);
                tempList.add(cl);
            }
            // 更新ViewModel的数据
            sharedViewModel.setCatList(tempList);
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            throw databaseError.toException();
        }
    });
}
  1. 在第二个Fragment中监听ViewModel的数据
private SharedViewModel sharedViewModel;

// 在onViewCreated生命周期中初始化
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
// 监听列表变化,只要数据更新就会回调
sharedViewModel.getCatList().observe(getViewLifecycleOwner(), catList -> {
    // 这里直接拿到最新的列表,不需要主动调用Dashboard的方法
    System.out.println(catList.size());
    // 后续处理列表的逻辑写在这里
});

方案2:通过宿主Activity中转

如果不想用ViewModel,也可以让两个Fragment的共同宿主Activity持有列表,或者持有Dashboard的实例:

  1. 在宿主Activity中定义公共方法返回Dashboard实例
// 宿主Activity中
public Dashboard getDashboardFragment() {
    // 如果你是用ViewPager或者导航组件的话,对应调整获取Fragment的方式
    return (Dashboard) getSupportFragmentManager().findFragmentByTag("dashboard_tag");
}
  1. 第二个Fragment中先从Activity获取Dashboard实例再调用方法
// 第二个Fragment中
Dashboard db = ((你的宿主Activity类名) requireActivity()).getDashboardFragment();
if (db != null) {
    List<Catergory_List> TExpenses= db.TrasactionExpenses();
    System.out.println(TExpenses.size());
}

注意:这个方案还是需要你自己处理Firebase异步加载的问题,确保调用方法时数据已经加载完成

额外提示

注意代码里的类名、方法名存在拼写错误(Catergory应为Category,Trasaction应为Transaction),建议统一修正避免后续开发出错。


内容的提问来源于stack exchange,提问作者Android God

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 21:12:00