无法获取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
相关产品推荐
相关产品推荐

