【问题标题】:ViewModel - change parameter of method while observing LiveData at runtime?ViewModel - 在运行时观察 LiveData 时更改方法的参数?
【发布时间】:2018-11-16 23:37:08
【问题描述】:

我正在尝试找出 MVVM(这对我来说很新),并且我想出了如何使用 Room 和 ViewModel 观察 LiveData。现在我面临一个问题。

我有一个需要参数的 Room 查询,这就是我开始在 MainActivity 的 onCreate 中观察 LiveData 的方式。

    String color = "red";
    myViewModel.getAllCars(color).observe(this, new Observer<List<Car>>() {
            @Override
            public void onChanged(@Nullable List<Car> cars) {
                adapter.setCars(cars);
            }
        });

通过使用此代码,我收到“红色”汽车的列表并使用该列表填充 RecyclerView。

现在我的问题是 - 有没有办法更改 getAllCars 方法中的 color 变量(例如通过按钮单击)并影响观察者返回新列表?如果我只是改变颜色变量,什么都不会发生。

【问题讨论】:

    标签: android mvvm


    【解决方案1】:

    in this answer 所述,您的解决方案是Transformation.switchMap

    来自Android for Developers website:

    LiveData switchMap(LiveData触发器,Function>func)

    创建一个 LiveData,我们将其命名为 swLiveData,它遵循下一个流程:它对 触发器 LiveData 的变化,将给定函数应用于新值 触发 LiveData 并将生成的 LiveData 设置为“支持” LiveData 到 swLiveData。 “支持”LiveData 意味着,所有事件 它发出的将由 swLiveData 重新传输。

    在你的情况下,它看起来像这样:

    public class CarsViewModel extends ViewModel {
        private CarRepository mCarRepository;
        private LiveData<List<Car>> mAllCars;
        private LiveData<List<Car>> mCarsFilteredByColor;
        private MutableLiveData<String> filterColor = new MutableLiveData<String>();
        
        public CarsViewModel (CarRepository carRepository) {
            super(application);
            mCarRepository= carRepository;
            mAllCars = mCarRepository.getAllCars();
            mCarsFilteredByColor = Transformations.switchMap(
                filterColor,
                color -> mCarRepository.getCarsByColor(color)
            );
        }
        
        LiveData<List<Car>>> getAllCars() { return mAllCars; }
        LiveData<List<Car>> getCarsFilteredByColor() { return mCarsFilteredByColor; }
    
        // When you call this function to set a different color, it triggers the new search
        void setFilter(String color) { filterColor.setValue(color); }
    }
    

    因此,当您从视图中调用 setFilter 方法时,更改 filterColor LiveData 将触发 Transformation.switchMap,后者将调用 mRepository.getCarsByColor(c)),然后使用查询结果更新 mCarsFilteredByColor LiveData。因此,如果您在视图中观察此列表并设置不同的颜色,则观察者会收到新数据。

    【讨论】:

    • 这对我很有帮助,因为我必须根据用户选择的各种排序选项从 Room 中获取数据。早些时候,我以一种非常不寻常的方式来做这件事。谢谢!
    • 您的代码帮助很大。但是这行有一个问题:private LiveData&lt;String&gt; filterColor = new MutableLiveData&lt;String&gt;(); 而不是使用private MutableLiveData&lt;String&gt; filterColor = new MutableLiveData&lt;String&gt;();,因为 LiveData's setValue() 具有受保护的访问权限,而 MutableLiveData's setValue() 具有公共访问权限.
    • @SayokMajumder 你是对的,谢谢!答案已编辑。
    【解决方案2】:

    除了@dglozano 的答案,一种简单的方法是观察color 而不是观察list。在colorvalueChange 上,获取新列表。

    例子:

    ViewModel 类中这样做

    MutableLiveData<String> myColor = new MutableLiveData<String>();
    

    Activity 中这样做:

    button.setOnClickListener(new OnClickListener() {
    public void onClick(View v)
    {
        myViewModel.myColor.setValue("newColor");
    } });
    
    myViewModel.myColor.observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable String newValue) {
               // do this on dedicated thread
               List<Car> updateList = myViewModel.getCarsByColor(newValue)
               // update the RecyclerView
            }
        });
    

    注意: 1.getCarsByColor() 不需要包装成LiveDataDao 中的方法可以返回List&lt;Cars&gt; 而不是LiveData&lt;List&lt;Cars&gt;&gt;

    2.不要在主线程上运行db查询,调用notifyDataSetChanged刷新RecyclerView。

    【讨论】:

    • 不知道你想在这里实现什么。当您已经通过 onClick 方法知道颜色值的变化时,为什么还要使用观察者来“观察”颜色?从某种意义上说,您自己设置了一个值,然后通过观察者获得相同的值,这是毫无意义的。
    猜你喜欢
    • 2020-03-17
    • 2018-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多