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

无法获取ViewModel实例求助:Fragment中ViewModel初始化异常

问题分析与修复方案

核心问题点

你遇到的空指针异常,根源是多个对象未初始化、关键方法未执行,以及数据处理逻辑错误。


1. MaterialViewModel 未调用 init() 方法,导致 matts 为 null

在HomeFragment中获取ViewModel实例后,没有执行init()方法,matts始终处于null状态,调用getMaterials().observe()必然触发空指针。

修复代码(HomeFragment):

public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {
    binding = FragmentHomeBinding.inflate(inflater, container, false);

    // 用Fragment自身作为ViewModel所有者,避免不必要的跨组件实例共享
    materialViewModel = new ViewModelProvider(this).get(MaterialViewModel.class);
    // 必须调用init初始化LiveData
    materialViewModel.init();

    initializeRecyclerView();
    getPosts();

    return binding.getRoot();
}

2. MaterialRepository 中 mattis 和 dataIsLoaded 未初始化

这两个MutableLiveData对象没有在构造方法中实例化,后续调用setValue()会直接抛出空指针。

修复代码(MaterialRepository):

public MaterialRepository(Application application) {
    super();
    service = RetrofitClass.getClient(application).create(API_Service.class);
    // 初始化LiveData对象,默认状态设为合理值
    mattis = new MutableLiveData<>();
    dataIsLoaded = new MutableLiveData<>(false);
}

3. Retrofit 请求的数据处理逻辑错误

  • 将response.body()转成String是完全错误的操作,直接使用返回的List<MaterialModel>即可
  • 注释了MyTask导致数据无法传递给mattis
  • 未处理请求失败的边界情况

修复代码(MaterialRepository的getAllMaterials方法):

public MutableLiveData<List<MaterialModel>> getAllMaterials() {
    Call<List<MaterialModel>> postResponseCall = service.getMaterials();

    postResponseCall.enqueue(new Callback<List<MaterialModel>>() {
        @Override
        public void onResponse(Call<List<MaterialModel>> call, Response<List<MaterialModel>> response) {
            if (response.isSuccessful() && response.body() != null) {
                Log.w("PAR-RESPONSE-CODE ", String.valueOf(response.code()));
                // 直接将接口返回的列表传入LiveData
                mattis.setValue(response.body());
                dataIsLoaded.setValue(true);
            } else {
                // 处理请求成功但无数据的情况
                mattis.setValue(new ArrayList<>());
                dataIsLoaded.setValue(true);
            }
        }

        @Override
        public void onFailure(Call<List<MaterialModel>> call, Throwable t) {
            // 处理请求失败场景
            Log.e("PAR-FAILURE", t.getMessage());
            mattis.setValue(new ArrayList<>());
            dataIsLoaded.setValue(true);
        }
    });
    return mattis;
}

如果MyTask是用于额外数据解析/处理的,取消注释并确保将response.body()正确传入任务,而非转成String。

4. Fragment 中 Observer 生命周期优化

使用viewLifecycleOwner代替getActivity()作为Observer的生命周期所有者,避免Fragment视图销毁后仍持有引用导致内存泄漏,同时用安全的布尔值判断避免空指针。

修复代码(HomeFragment的getPosts和getIsLoaded方法):

private void getPosts() {
    materialViewModel.getMaterials().observe(getViewLifecycleOwner(), new Observer<List<MaterialModel>>() {
        @Override
        public void onChanged(@Nullable List<MaterialModel> posts) {
            binding.rvMain.setAdapter(new ItemAdapter((ArrayList<MaterialModel>) posts));
        }
    });
    getIsLoaded();
}

public void getIsLoaded(){
    materialViewModel.getIsLoaded().observe(getViewLifecycleOwner(), new Observer<Boolean>() {
        @Override
        public void onChanged(@Nullable Boolean aBoolean) {
            if (Boolean.TRUE.equals(aBoolean)){
                Log.w("PAR-LOADED ", "DATA IS LOADED");
            }
        }
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 14:20:40