はじめに
DataBindingを使ってテキストを動的に変更するの応用版として
DataBindingを使ってログイン機能を実装してみた。(ログイン画面後のUIは適当なのでコード割愛)
ログイン成功時 | ログイン失敗時 |
---|---|
![]() |
![]() |
単方向と双方向バインディングの違いをおさえる
@{}
:単方向バインディングの特徴
- ViewModelの値を変更する -> Viewに自動で反映される
- ユーザーがViewの値を変更する -> ViewModelに反映されない
- ViewModelにget〇〇〇メソッドを定義する必要がある
@={}
:双方向バインディングの特徴
- ViewModelの値を変更する -> Viewに自動で反映される
- ユーザーがViewの値を変更する -> ViewModelに自動で反映される
- ViewModelにget〇〇〇メソッドとset〇〇〇メソッドを定義する必要がある
コード
DataBindingの導入
appのgradleに以下を追加
build.gradle
android {
dataBinding {
enabled = true
}
}
クリックイベントのインターフェースを定義
EventHandlers.java
public interface EventHandlers {
void onLoginClick(View view);
}
ViewModel
UserViewModel.java
public class UserViewModel extends BaseObservable {
private String email;
private String password;
private String clickText;
@Bindable public String getEmail() { return email; }
@Bindable public String getPassword() { return password; }
@Bindable public String getClickText() { return clickText; }
// フォームへの入力有無で、ボタン活性・非活性を制御(getEmail()等と同じgetter)
@Bindable public boolean isButtonEnable() {
// 入力あり:true 入力なし:false
return !TextUtils.isEmpty(email) && !TextUtils.isEmpty(password);
}
// Emailフォームに値を入力・変更する度に呼び出される
public void setEmail(String email) {
this.email = email;
// この記述でisButtonEnable()が呼ばれる
notifyPropertyChanged(BR.buttonEnable);
}
// Passwordフォームに値を入力・変更する度に呼び出される
public void setPassword(String password) {
this.password = password;
// この記述でisButtonEnable()が呼ばれる
notifyPropertyChanged(BR.buttonEnable);
}
// 入力値のバリデーションチェック
public boolean isValidInputValue() {
if (email.length() >= 6 && password.length() >= 6) {
return true;
}
return false;
}
}
layout
- EditTextはユーザーがViewの値を更新するので必ず双方向バインディングとなる。
- android:enabledでボタンが押せる,押せないを判定できる。
activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.example.loginapp.UserViewModel" />
<variable
name="handlers"
type="com.example.loginapp.EventHandlers" />
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/clickText"
android:layout_width="320dp"
android:layout_height="wrap_content"
android:text="@{user.clickText}"/>
<EditText
android:id="@+id/mail_form"
android:layout_width="320dp"
android:layout_height="wrap_content"
android:imeOptions="actionDone"
android:inputType="textEmailAddress"
android:text="@={user.email}"/>
<EditText
android:id="@+id/pass_form"
android:layout_width="320dp"
android:layout_height="wrap_content"
android:imeOptions="actionDone"
android:inputType="textPassword"
android:text="@={user.password}"/>
<Button
android:id="@+id/login"
android:layout_width="320dp"
android:layout_height="wrap_content"
android:text="ログイン"
android:enabled="@{user.buttonEnable}"
android:onClick="@{handlers.onLoginClick}"/>
</LinearLayout>
</layout>
Activity
LoginActivity.java
public class LoginActivity extends AppCompatActivity implements EventHandlers {
ActivityLoginBinding binding;
UserViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// Bindingのインスタンスを取得
binding = DataBindingUtil.setContentView(this, R.layout.activity_login);
// xmlのuserにLoginActivityのUserViewModelを紐付ける
viewModel = new UserViewModel();
binding.setUser(viewModel);
// xmlのhandlersにLoginActivityのonLoginClick()を紐付ける
binding.setHandlers(this);
}
// buttonをクリックしたときのイベント処理
@Override
public void onLoginClick(View view) {
if (viewModel.isValidInputValue()) {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
} else {
binding.clickText.setText("6文字以上入力してください");
}
}
}