Question
Two-Way DataBinding allows you to automatically populate UI components with data from an Object and then automatically update the Object as the user edits those UI components.
As the user edits UI components, is there a way to not only automatically update the Object in memory, but automatically update/persist the Object in a Room database?
I could manually listen to every UI field modification and manually save the Object to the Room Database. However, such a manual, brute force approach would negate the benefits of Two-Way DataBindings that I'm hoping to utilize.
Context
My application stores Items in an SQLite database using Android's Room Persistence Library. This is a simplified version of my Item:
@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;
}
}
The magic of ViewModel, LiveData, and Two-Way DataBindings allows my ItemEditorFragment to automatically populate the UI with data from the selected Item and to update that Item when the user edits the UI components:
@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;
}
This is a simplified version of the layout being inflated:
<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>
The Room persistence library provides an abstraction layer over SQLite to allow for more robust database access while harnessing the full power of SQLite. Latest Update.
Two-way data binding refers to sharing data between a component class and its template. If you change data in one place, it will automatically reflate at the other end. For example, if you change the value of the input box, then it will also update the value of the attached property in a component class.
Room autogenerates implementations of your @Database and @Dao annotated classes the first time you compile your code after creating a Room Database. The implementation of UserDatabase and UserDao in the preceding example is generated automatically by the Room annotation processor.
Two-way Data Binding is a technique of binding your objects to your XML layouts so that the layout can send data to your binding object. This is compared to a “traditional” or “one-way” Data Binding setup, where data would only move from your binding object to the layout.
One of the dirty hacks I've made work is: creating a new property, in the ViewModel
(but it doesn't strictly have to be exactly there), without a backing field (in Java, this would probably equate to creating a getter and a setter, without a field):
var selectedItemName: String?
get() = selectedItem.value?.name
set(value) {
selectedItem.value?.let {
it.name = value
dao.update(it)
}
}
This is not an ideal solution, since it requires mirroring all of the properties in the class, but it works if you just want to get it over with. I'm awaiting a better solution!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With