首页 > 解决方案 > 数据更改时未调用 LiveData onChanged

问题描述

我是新手LiveDataViewModels我不完全了解数据是如何更新的。

根据Android 开发网站

无需在每次应用数据更改时更新 UI,您的观察者可以在每次发生更改时更新 UI。

这句话对我没有意义。我正在使用 Sqlite 数据库(没有 Room),并且我getItems()ViewModel. 这是否意味着当在数据库中添加或更新数据时,LiveData会自动检测并onChange调用它?

根据 Android 开发网站,它说要开始LiveData观察onCreate. 在使用之前,我通过查询数据库然后调用来LiveData刷新数据。onResumenotifyDataSetChanged()

这段代码我现在在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);
    }

}

标签: androidandroid-livedataandroid-viewmodel

解决方案


如果private MutableLiveData<List<String>> items尚未初始化,则仅检索一次项目:

public MutableLiveData<List<String>> getItems() {
    if (items == null) {
        items = new MutableLiveData<>();
        getItems();// it's called only once 
    }
    return items;
}

解决此问题的一种方法可能是ContentObserver用于您的数据:

...
private final ContentObserver contentObserver = new ContentObserver(new Handler()) {
    @Override
    public void onChange(boolean selfChange) {
        // if there're any changes then perform the request and update the UI
        getItems(); 
    }
};
...

不要忘记注册它以获取数据库更改的通知:

...
contentResolver.registerContentObserver(<your data content uri>, true, contentObserver);
...

我还建议创建一个Repository负责数据检索的单独层,如下所示:

...
private final ContentObserver contentObserver = new ContentObserver(new Handler()) {
    @Override
    public void onChange(boolean selfChange) {
        // if there're any changes then perform the request and update the UI
        getItems(); 
    }
};

public LiveData<List<String>> getItems() {
    return new MutableLiveData<String>() {
        @Override
        public void onActive() {
           // your async operation here
           new Thread({
               List<String> items = db.getItems();
               postValue(items);
           }).start();

           contentResolver.registerContentObserver(<your data content uri>, true, contentObserver); 
        }

        @Override
        public void onInactive() {
            contentResolver.unregisterContentObserver(contentObserver); 
        }
    }
    return liveData;
}   
... 

然后,您ViewModel将需要注入存储库对象,因此需要ViewModelFactory构建您的实例,ViewModel但整体用法看起来类似于:

public class MyViewModel extends AndroidViewModel {   
    ... 
    public MutableLiveData<List<String>> getItems() {
        dataRepository.getItems();
    }
    ...
}

要获取更多信息,请阅读应用架构指南


推荐阅读