Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I do databinding with livedata?

How can I do databinding with livedata?

activity_user_detail.xml:

<data>
    <variable
        name="viewModel"
        type="com.test.viewmodel.UserViewModel" />
</data>
<TextView
        android:id="@+id/tv_amount"
        android:layout_width="match_parent"
        android:text="@{viewModel.age}"
 ....

UserViewModel.java:

public class UserViewModel extends ViewModel {
    public LiveData<User> user;
    public void getUserById(UserDao userDao, String userId){
        transaction = UserDao .load(userId);
    }
}

UserDao.java:

@Query("SELECT * FROM `user` WHERE id = :userId")
LiveData<User> load(String userId);

UserDetailActivity.java:

private ActivityUserDetailBinding binding;
binding = DataBindingUtil.setContentView(this, R.layout.activity_user_detail);
viewModel = ViewModelProviders.of(this).get(UserViewModel.class);
viewModel.getUserById(userDao, userId);
viewModel.user.observe(this, user -> binding.setViewModel(user)); // How to bind livedata?

I have tried this also:

binding.setViewModel(viewModel);
like image 974
Alvin Avatar asked Jul 11 '18 14:07

Alvin


People also ask

Can we use databinding in MVP?

Why use Data binding with Mvp? Combining Databinding along wih MVP pattern can result in a very clean structure and maintainable project. Databinding saves u a lot of stress and uneccesary long lines of code. Your UI is updated eaily and gone are those days where you need "findViewById" and onclick listeners and so on.

Can we use both viewBinding and databinding?

View binding doesn't support layout variables or layout expressions, so it can't be used to declare dynamic UI content straight from XML layout files. View binding doesn't support two-way data binding.

When should I use databinding?

Data Binding allows you to effortlessly communicate across views and data sources. This pattern is important for many Android designs, including model view ViewModel (MVVM), which is currently one of the most common Android architecture patterns.

What is data binding with livedata?

Data Binding with LiveData. Data Binding with LiveData makes our code more concise. It allows layouts to directly communicate with ViewModels. We created a simple code example during our LIveData tutorial.

Does livedata always need a lifecycle?

LiveData always need a lifecycle. But, in this code LiveData directly work with data binding. So, we should set the activity (this activity) as the lifecycle owner to the data binding instance. Here is the final MainActivity.kt code.

What is livedata in Android?

To understand that, you should be good with the basics. In simple terms, LiveData is an observable data holder class. This means it can hold a set of data that can be observed from other Android components like Activities, Fragments, and Services. It’s lifecycle-aware and mostly used to update UI from the ViewModel in MVVM architecture projects.

How to observe a livedata object as an observable field?

You can now use a LiveData object as an observable field in data binding expressions. The ViewDataBinding class now includes a new setLifecycle method that you need to use to use to observe LiveData objects. Show activity on this post.


1 Answers

This is a sample to figure out how LiveData and ObservableField works. You need to change T object and setValue() with LiveData, or set(T) with ObservableField. Changing properties of object T does not update UI.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="viewModel"
            type="com.example.tutorial3livedata_databinding2objects.UserViewModel" />
    </data>

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/user_info"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text='@{viewModel.userMutableLiveData.name+ ", email " + viewModel.userMutableLiveData.email}'
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.501"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.1" />

        <EditText
            android:id="@+id/et_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="48dp"
            android:text="@={viewModel.userMutableLiveData.name}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.501"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/user_info" />

        <EditText
            android:id="@+id/et_email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="28dp"
            android:text="@={viewModel.userMutableLiveData.email}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.501"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/et_name" />

        <Button
            android:id="@+id/button_change_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:onClick="@{() -> viewModel.changeUserName()}"
            android:text="Change Name"
            app:layout_constraintEnd_toStartOf="@+id/button_change_user"
            app:layout_constraintHorizontal_chainStyle="spread"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/et_email" />

        <Button
            android:id="@+id/button_change_user"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{() -> viewModel.changeUser()}"
            android:text="Change User"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/button_change_name"
            app:layout_constraintTop_toTopOf="@+id/button_change_name" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="56dp"
            android:text="Display User"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/button_change_name" />

    </android.support.constraint.ConstraintLayout>
</layout>

ViewModel

public class UserViewModel extends ViewModel {

    public MutableLiveData<User> userMutableLiveData = new MutableLiveData<>();
    private User mUser;

    public UserViewModel() {
        mUser = new User("User", "[email protected]");
        userMutableLiveData.setValue(mUser);

    }

    public void changeUserName() {

        // Both updates LiveData but does not update UI
        mUser.setName("Name is Changed");
        // userMutableLiveData.getValue().setName("Updated Name");

        // This one Updates UI
        //  userMutableLiveData.setValue(userMutableLiveData.getValue());
    }

    public void changeUser() {
        mUser = new User("New User Name", "[email protected]");
        // Without setting new value UI is not updated and observe is not called
        userMutableLiveData.setValue(mUser);
    }
}

MainActivity

/*
    Without binding.setLifecycleOwner(this), liveData.setValue() does not update UI
    liveData.setValue() updates UI 
    EditText changes LiveData but does not update UI
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        UserViewModel userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
        // LiveData should call setValue() to update UI via binding
        binding.setViewModel(userViewModel);

        // Required to update UI with LiveData
        binding.setLifecycleOwner(this);
    }
}

This code is for learning purposes.

Results you can get from this code:

1- Changing user name with changeUserName() updates the name of existing User of LiveData but does not update UI. UI gets updated when you rotate the device.

2- When you change User of LiveData and setValue() data-binding works.

3- Changing User properties using EditText 2-way binding android:text="@={viewModel.userMutableLiveData.name}" changes LiveData's User's name but does not update UI until device is rotated since User is still same.

like image 88
Thracian Avatar answered Oct 12 '22 22:10

Thracian