android - 数据更改时未调用 LiveData onChanged
问题描述
我是新手LiveData
,ViewModels
我不完全了解数据是如何更新的。
根据Android 开发网站:
无需在每次应用数据更改时更新 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);
}
}
解决方案
如果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();
}
...
}
要获取更多信息,请阅读应用架构指南
推荐阅读
- python - 在 PyCharm 中编写 HTML
- tensorflow - Keras 均方差损失
- html - 如何使用 HTML 格式剪切标签文本的结尾
- cakephp - PHP 7.3/7.4 的最低 CakePHP 版本?
- mysql - 选择没有。基于两个表中的值的人数
- jenkins - 如何使用 Jenkins Groovy 脚本创建 JSON 文件并向其写入键值对
- flutter - flutter path_provider 无法读取下载的文件
- c# - 具有多个列表的嵌套 LINQ
- python - 如何使用 OpenCV 和 Python 在图像上查找边框坐标
- database - 雪花没有为时间戳选择默认值