I'm using DataBinding with the following layout. I'm calling the setViewModel() method on the binding object. If I immediately call binding.getViewModel(), it returns null. See code below:
Layout:
<layout>
<data>
<variable
name="viewModel"
type="reyes.r.christopher.spenderbender.viewmodel.TransactionViewModel"/>
</data>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/viewExpenseListTable"
android:shrinkColumns="*"
android:stretchColumns="*"
>
</TableLayout>
</ScrollView>
</layout>
Activity:
public class ViewExpenseListActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityViewExpenseListBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_view_expense_list);
LocalDatabaseHandler dbh = new LocalDatabaseHandler(this);
TransactionViewModel viewModel = new TransactionViewModel(dbh);
binding.setViewModel(viewModel);
if ( BuildConfig.DEBUG ) {
if (viewModel == null) {
throw new AssertionError("Somehow viewModel is null...");
}
if(binding.getViewModel() == null) {
// This Assertion is always thrown
throw new AssertionError("viewModel is not null, but wasn't set in the binding");
}
}
// Throws NullPointerException
binding.getViewModel().loadAllExpenses();
}
...
}
You may notice that I'm not using the variable anywhere in the layout. I'm trying to programmatically replace the rows in the table with values from the database whenever new rows are added to the database. That's why I need to get the viewModel from the binding.
PS: I found this similar question: Android Databinding Adapter Null Pointer Exception. This person was getting a Null Pointer Exception when they called the set method, not the get method. I can call the set method just fine, but the get returns a null object.
Turns out, if the variable isn't referenced in the layout, then the generated setters and getters aren't implemented.
I decided to post this in case anyone else had a similar question in the future, but I discovered this upon investigating the generated file. Here's what the getViewModel() and setViewModel() methods look like in the generated ActivityViewExpenseListBinding class:
public void setViewModel(reyes.r.christopher.spenderbender.viewmodel.TransactionViewModel viewModel) {
// not used, ignore
}
public reyes.r.christopher.spenderbender.viewmodel.TransactionViewModel getViewModel() {
return null;
}
I need to either reference the viewModel variable from within the layout, or use a different pattern for observing changes.
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