I searched a lot about observable models and parameters but I got confused!
1-some of model extend from BaseObservable
and setnotifyChange();
in setters and bind them for example to edittext like this: app:addTextChangedListener="@{viewModel.getEmailTextWatcher}"
and that notifyChange()
update text by changing email
parameter of user
model.
2-and some of them use livedata
for observing and change UI in onChanged()
method.
How can I use liveData
and change UI by databinding
? not by onChanged()
.
and when onChanged()
use while we can use databinding
for UI changes?
edited: here is my coded:
public class MainActivity extends AppCompatActivity implements LoginResultCallback {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
activityMainBinding.setViewModel(ViewModelProviders.of(this, new LoginViewModelFactory(this)).get(LoginViewModel.class));
}
@Override
public void onSuccess(String s) {
Toasty.success(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
}
@Override
public void onError(String s) {
Toasty.error(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
}
}
and here is interface:
public interface LoginResultCallback {
void onSuccess(String s);
void onError(String s);
}
and here is User model:
public class User {
@NonNull
public String mEmail;
public User(@NonNull final String email, @NonNull final String password) {
mEmail = email;
}
@NonNull
public String getEmail() {
return mEmail;
}
public void setEmail(@NonNull final String email) {
mEmail = email;
}
}
here is ViewModel:
public class LoginViewModel extends ViewModel {
public MutableLiveData<User> user = new MutableLiveData<>();
;
private LoginResultCallback mDataListener;
LoginViewModel(@NonNull final LoginResultCallback loginDataListener) {
mDataListener = loginDataListener;
if (user != null) {
//help me fill here
}
}
public TextWatcher getEmailTextWatcher() {
return new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
//help me fill here
}
};
}
}
here is layout:
<?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......viewmodels.LoginViewModel" />
</data>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="8dp"
android:orientation="vertical">
<EditText
android:id="@+id/test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="test"
android:padding="8dp"
android:text="@{viewModel.user}" />
<EditText
android:id="@+id/inEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"
android:inputType="textEmailAddress"
android:padding="8dp"
app:addTextChangedListener="@{viewModel.getEmailTextWatcher}" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:onClick="@{viewModel::onLoginClicked}"
android:text="LOGIN" />
</LinearLayout>
</ScrollView>
i just want to change inEmail
edittext and upper edittext change by data binding
First, enable data binding in your app level build.gradle
as follows:
android {
...
dataBinding {
enabled = true
}
...
}
Make sure you have lifecycle
dependencies as well:
dependencies {
...
implementation "android.arch.lifecycle:runtime:1.1.1"
implementation "android.arch.lifecycle:extensions:1.1.1"
annotationProcessor "android.arch.lifecycle:compiler:$versions.lifecycle:1.1.1"
...
}
Now, let's say you have some User
class:
public class User {
private String firstName;
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
}
Then, you could have some UserLiveData
:
public class UserLiveData extends LiveData<User> {
public UserLiveData() {
setValue(new User());
}
}
Here's a simple UserViewModel
:
public class UserViewModel extends ViewModel {
private UserLiveData liveData;
public UserViewModel() {
liveData = new UserLiveData();
}
public void observeLiveDate(LifecycleOwner owner,
Observer<User> observer) {
liveData.observe(owner, observer);
}
}
Now, activity_main.xml
defines layout with the user's first name EditText
and Button
:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="@={user.firstName}"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/load_button"
android:text="Load"/>
</LinearLayout>
Please note @={user.firstName}
. It's needed for a 2-way data binding. Every time the user types something in the EditText
, it's updated in the User
object as well. Also, refresh the Gradle project so that to generate data binding files like.
In the end, MainActivity
uses ViewModel
to preserve bound User
on config changes. So, you type something and rotate the screen, EditText
will keep the text. Here's the code:
public class MainActivity extends AppCompatActivity {
private UserViewModel viewModel;
private ActivityMainBinding mainBinding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainBinding = DataBindingUtil.setContentView(this,
R.layout.activity_main);
mainBinding.setLifecycleOwner(this);
viewModel = ViewModelProviders.of(this)
.get(UserViewModel.class);
viewModel.observeLiveDate(this, user -> {
// set initial User object
mainBinding.setUser(user);
});
mainBinding.loadButton.setOnClickListener(v -> {
// show the current first name
Toast.makeText(v.getContext(), "first name : " + mainBinding.getUser().getFirstName(), Toast.LENGTH_LONG).show();
});
}
}
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