android-room - 使用 Room 自动持久化双向数据绑定的更改?
问题描述
问题
双向数据绑定允许您使用来自对象的数据自动填充 UI 组件,然后在用户编辑这些 UI 组件时自动更新对象。
当用户编辑 UI 组件时,有没有办法不仅自动更新内存中的对象,而且自动更新/持久化 Room 数据库中的对象?
我可以手动监听每个 UI 字段修改并手动将对象保存到房间数据库。但是,这种手动的蛮力方法会否定我希望利用的双向数据绑定的好处。
语境
我的应用程序使用 Android 的 Room Persistence Library 将项目存储在 SQLite 数据库中。这是我的项目的简化版本:
@Entity
public class Item {
@PrimaryKey(autoGenerate = true)
private long id;
private String name;
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
ViewModel、LiveData 和双向数据绑定的魔力允许我的 ItemEditorFragment 使用来自所选项目的数据自动填充 UI,并在用户编辑 UI 组件时更新该项目:
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof ItemViewModelProvider) {
final ItemViewModelProvider itemViewModelProvider = (ItemViewModelProvider) context;
mViewModel = itemViewModelProvider.getItemViewModel();
} else {
throw new RuntimeException(context.toString()
+ " must implement ItemViewModelProvider");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final FragmentItemEditorBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_item_editor, container, false);
binding.setViewModel(mViewModel);
binding.setLifecycleOwner(this);
final View view = binding.getRoot();
return view;
}
这是被膨胀的布局的简化版本:
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.lafave.ItemViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@={viewModel.selectedItem.name}"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
</layout>
解决方案
我所做的其中一个肮脏的技巧是:创建一个新属性,在ViewModel
(但它并不严格必须完全存在),没有支持字段(在 Java 中,这可能等同于创建一个 getter 和一个二传手,没有字段):
var selectedItemName: String?
get() = selectedItem.value?.name
set(value) {
selectedItem.value?.let {
it.name = value
dao.update(it)
}
}
这不是一个理想的解决方案,因为它需要镜像类中的所有属性,但如果您只是想完成它,它就可以工作。我正在等待更好的解决方案!
推荐阅读
- jenkins - 通过 sh 导航到 .jar
- java - 将格式化字符串解析为数组
- python - Errno 13 权限被拒绝。已经在虚拟环境中
- java - 决策和循环
- python - Pyinstaller pythonfile.py 启动器中的致命错误:无法使用“”创建进程
- matlab - 为什么在 parfor 中访问 2d 矩阵这么慢?
- python - 聚类许多坐标并放入 Folium
- python - 在 SQLAlchemy 中使用正确的文件结构以及如何将数据添加到 db
- user-interface - 最合适的 UI 设计模式和 JavaFX 问题?
- python - 使用“in”运算符时如何避免出现包含部分搜索字符串的字符串?