使用 MediatorLiveData 时出现 NullPointerException

Posted

技术标签:

【中文标题】使用 MediatorLiveData 时出现 NullPointerException【英文标题】:NullPointerException when using MediatorLiveData 【发布时间】:2022-01-19 18:13:45 【问题描述】:

我想显示一个可排序的餐厅列表。当我使用简单的 LiveData 时它可以工作,但我得到了 NullPointerException,因为我将它更改为 mediatorLiveData。

在片段中,我使用这些行来观察 mediatorLiveData

vm.getAllRestaurantsWithOrderMediatorLD().observe(getViewLifecycleOwner(), listRestaurants -> 
            datas.clear();
            datas.addAll(listRestaurants);
            adapter.notifyDataSetChanged();
        );

这里是视图模型类:

public class ListRestaurantsViewModel extends ViewModel 

    private final RestaurantRepository restaurantRepository;
    private final SortRepository sortRepository;
    private final MutableLiveData<List<RestaurantViewState>> allRestaurantsViewStateLD = new MutableLiveData<>();
    private final MutableLiveData<SortRepository.OrderBy> orderLiveData = new MutableLiveData<>();
    private final MediatorLiveData<List<RestaurantViewState>> allRestaurantsWithOrderMediatorLD;

    Context ctx;

    public ListRestaurantsViewModel(RestaurantRepository restaurantRepository, SortRepository sortRepository, Context ctx) 
        this.ctx = ctx;
        this.restaurantRepository = restaurantRepository;
        this.sortRepository = sortRepository;

        allRestaurantsWithOrderMediatorLD = new MediatorLiveData<>();
        allRestaurantsWithOrderMediatorLD.addSource(getAllRestaurantsViewStateLD(), value -> allRestaurantsWithOrderMediatorLD.setValue(value));

        allRestaurantsWithOrderMediatorLD.addSource(getOrderLiveData(), order -> 
                                                       
                      List<RestaurantViewState> restaurants = getAllRestaurantsViewStateLD().getValue();
                      if (restaurants != null && !restaurants.isEmpty()) 
                      List<RestaurantViewState> newList = new ArrayList<>();
                      if (order == SortRepository.OrderBy.DISTANCE)
                                                                newList =
                                                                        Stream.of(restaurants).sorted((a, b) -> a.getDistance() - b.getDistance()).toList();

                     else if (order == SortRepository.OrderBy.RATING)
                                                                newList = Stream.of(restaurants).sorted((a, b) -> Double.compare(a.getStarsCount(),
                                                                                                                                 b.getStarsCount())).toList();

         allRestaurantsWithOrderMediatorLD.setValue(newList);
        
    
);
    

    public MediatorLiveData<List<RestaurantViewState>> getAllRestaurantsWithOrderMediatorLD() 
        return allRestaurantsWithOrderMediatorLD;
    

    public LiveData<SortRepository.OrderBy> getOrderLiveData() 
        return sortRepository.getOrderLiveData();
    

    public LiveData<List<RestaurantViewState>> getAllRestaurantsViewStateLD() 
        return Transformations.map(restaurantRepository.getRestaurantsLiveData(), restaurantsList -> 
            List<RestaurantViewState> restaurantViewStates = new ArrayList<>();
            for (Restaurant r : restaurantsList) 

                restaurantViewStates.add(new RestaurantViewState(
                                                 r.getId(),
                                                 r.getName(),
                                                 r.getType(),
                                                 r.getAdress(),
                                                 r.getImage()
                                         )
                                        );
            
            return restaurantViewStates;
        );
    

这是错误,我明白了 java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.lifecycle.LiveData.observeForever(androidx.lifecycle.Observer)' on a null object reference

如果我观察片段中的 livedata getAllRestaurantsViewStateLD() 没有错误,所以我认为我在使用 mediatorLiveData 时没有得到任何东西 你看出来是什么了吗?

【问题讨论】:

【参考方案1】:

调用observeForever 时发生崩溃,但您的代码 sn-p 并未显示您正在使用它。所以问题出在其他地方。

【讨论】:

我不确定 observeForever 是什么。我不在任何地方使用它。 AFAIK observeForever 由中介实时数据在内部调用,如果 OP 发布了他的异常堆栈而不是单独的错误消息,那么也许可以确定他自己的代码的哪一行触发了它。 错误信息中提到的那一行与MediatorLiveData.java中的void plug() mLiveData.observeForever(this); 这个函数有关 @Emmcy 在这种情况下mLiveData 为空。试着理解为什么会这样。 对我来说似乎很奇怪的是,它可以与它的一个来源一起工作(如果我观察到第一个 LiveData 就不会崩溃)。如果 mediatorLiveData 的来源不是,我不明白它如何为空

以上是关于使用 MediatorLiveData 时出现 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章

Jetpack之LiveData扩展MediatorLiveData

具有多个参数的 MediatorLiveData 或 switchMap 转换

使用 CASE WHEN 语句时出现 RODBC“无效字符\n”错误

数据绑定 - MediatorLiveData 未在 Fragment 内触发

在 GWT 中使用 RPC 时出现 IncompatibleRemoteServiceException

当我尝试使用 ROW_NUMBER() 时出现错误,为啥?