Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android DataBinding setVariable() followed by getVariable() call returns null

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.

like image 823
Chris Reyes - he-him Avatar asked Aug 27 '16 21:08

Chris Reyes - he-him


1 Answers

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.

like image 82
Chris Reyes - he-him Avatar answered Sep 27 '22 17:09

Chris Reyes - he-him