[LiveData onChanged不会在数据更改时被调用

问题描述 投票:0回答:1

[我不熟悉LiveDataViewModels,并且我不完全了解如何更新数据。

根据Android Dev site

而不是每次应用程序数据更改时都更新UI,每次更改时,观察者都可以更新UI。

这句话对我来说毫无意义。我正在使用Sqlite数据库(没有Room),并且正在getItems()ViewModel方法中异步获取数据。这是否意味着在数据库中添加或更新数据时,LiveData将自动检测到它并调用onChange

据Android开发者网站称,它开始观察LiveData中的onCreate对象。在使用LiveData之前,我通过查询数据库然后调用onResume来刷新notifyDataSetChanged()中的数据。

此代码现在在加载Fragment时显示数据,但是如果我删除数据库或向数据库添加新数据,则UI不会反映更改。我只是认为我对LiveData的工作方式没有基本的了解,在任何地方都找不到很好的解释。

[帮助我StackOverflow,您是我唯一的希望。

public class MyViewModel extends AndroidViewModel {
    private MutableLiveData<List<String>> items;
    private Application application;

    public MyViewModel(@NonNull Application application) {
        super(application);
        this.application = application;
    }

    public MutableLiveData<List<String>> getItems() {
        if (items == null) {
            items = new MutableLiveData<>();
            getItems();
        }
        return items;
    }

    private void getItems() {
        List<String> items = GetItems(); //async process

        this.items.setValue(items)
    }
}

public class ListFragment extends Fragment {

    @Override
    public void onCreate(final Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        MyViewModel model = ViewModelProviders.of(getActivity()).get(MyViewModel.class);

        final Observer<List<String>> observer = new Observer<List<String>>() {
            @Override
            public void onChanged(List<String> items) {
                //update UI
            }
        };

        model.getItems().observe(this, observer);
    }

}
android android-livedata android-viewmodel
1个回答
0
投票

您的代码似乎正确。您正在正确设置所有内容,并且每次Observer值更改时,都会在ListFragment中的LiveData上收到回调。

但是,使用该代码,LiveData的值将永远不会改变,因此您的LiveData的Observer将仅被调用一次。您仅在MyViewModel.getItems中调用一次onCreate。此方法还将执行两件事:返回LiveData并获取项目列表。

第一种方法是将ViewModel getItems方法分为两种:一种用于获取LiveData,另一种用于刷新实际的项目列表。在片段中,您将像往常一样在onResume()中刷新数据。

看起来像这样:

public class MyViewModel extends ViewModel {
    private final MutableLiveData<List<String>> items = new MutableLiveData<>();

    public LiveData<List<String>> getItemsLiveData() {
        return items;
    }

    public void refreshItems() {
        List<String> items = GetItems(); //async process

        this.items.setValue(items)
    }
}

public class ListFragment extends Fragment {

    private MyViewModel model;

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        model = ViewModelProviders.of(getActivity()).get(MyViewModel.class);

        final Observer<List<String>> observer = new Observer<List<String>>() {
            @Override
            public void onChanged(List<String> items) {
                //update UI
            }
        };

        model.getItemsLiveData().observe(this, observer);
    }

    @Override
    public void onResume() {
        model.refreshItems()
    }
}

要走得更远,您将需要更改实际刷新项目的方式。如果要在修改数据库时在ViewModel中收到通知,则还需要在ViewModel与数据库之间的通信中使用Observer模式(带有LiveData的房间,RxJava的Observable或新的协程Flow是开始的好地方)] >

这里是使用RxJava的伪算法示例:

public class MyViewModel extends ViewModel {
    private final MutableLiveData<List<String>> items = new MutableLiveData<>();

    public MyViewModel() {
        myDatabase.getDatabaseObservable()
            .subscribe(new Subscriber<List<String>>() {
                @Override
                public void onCompleted() {
                }

                @Override
                public void onNext(List<String> newItems) {
                    items.setValue(newItems)
                }

                @Override
                public void onError() {
                }
            })
    }

    public LiveData<List<String>> getItemsLiveData() {
        return items;
    }
}

其中的最后一部分将在您的数据库类中创建该Observable(可以使用像Room一样自动运行的Library或通过创建自己的PublishSubject来创建。)>

© www.soinside.com 2019 - 2024. All rights reserved.