Java DataIndig向布局返回错误的onFocusChangeListener

Java DataIndig向布局返回错误的onFocusChangeListener,java,android,data-binding,android-databinding,Java,Android,Data Binding,Android Databinding,我有一个登录表单验证机制。电子邮件和密码有两个文本输入,都附加到各自的onFocusChangeListeners,使用数据绑定来设置它们,但数据绑定返回错误的侦听器 表格如下: <?xml version="1.0" encoding="utf-8"?> <layout> <data> <variable name="loginViewModel"

我有一个登录表单验证机制。电子邮件和密码有两个文本输入,都附加到各自的onFocusChangeListeners,使用数据绑定来设置它们,但数据绑定返回错误的侦听器

表格如下:

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="loginViewModel"
            type="com.example.increaseyouriq.ui.forms.LoginFormViewModel" />
    </data>
<LinearLayout
    android:id="@+id/ll_login"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    style="@style/parent.contentLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="26dp">

    <com.google.android.material.card.MaterialCardView
        style="@style/cardOutline"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="16dp">

            <TextView
                style="@style/viewParent.headerText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/login_title" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:orientation="vertical">

                <com.google.android.material.textfield.TextInputLayout
                    style="@style/textInputStyle"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:hint="@string/enter_email"
                    error="@{loginViewModel.loginForm.emailError}"
                    app:errorEnabled="@{loginViewModel.loginForm.isEmailError()}"
                    app:endIconMode="clear_text">

                    <com.google.android.material.textfield.TextInputEditText
                        android:id="@+id/et_login_email"
                        style="@style/textInputEditext"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        onFocus="@{loginViewModel.onFocusEmailChangeListener}"
                        android:text="@={loginViewModel.loginFields.email}"
                        android:inputType="textNoSuggestions|textEmailAddress" />

                </com.google.android.material.textfield.TextInputLayout>

                <com.google.android.material.textfield.TextInputLayout
                    style="@style/textInputStyle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/enter_password"
                    error="@{loginViewModel.loginForm.passwordError}"
                    app:errorEnabled="@{loginViewModel.loginForm.isPasswordError()}"
                    app:endIconMode="password_toggle">

                    <com.google.android.material.textfield.TextInputEditText
                        style="@style/textInputEditext"
                        android:id="@+id/et_login_password"
                        onFocus="@{loginViewModel.onFocusPasswordChangeListener}"
                        android:text="@={loginViewModel.loginFields.password}"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:inputType="textPassword" />

                </com.google.android.material.textfield.TextInputLayout>

            </LinearLayout>
        </LinearLayout>
    </com.google.android.material.card.MaterialCardView>

</LinearLayout>
</layout>
这是我的LoginActivity.java



public class LoginFormViewModel extends ViewModel {
    private static final String LOG_TAG = "LoginFormViewModel";

    private View.OnFocusChangeListener onFocusEmail;
    private View.OnFocusChangeListener onFocusPassword;


    public void init() {
        loginForm = new LoginForm();

        onFocusPassword = (v, hasFocus) -> {
            TextInputEditText et = (TextInputEditText) v;
            MyUtilsApp.showLog(LOG_TAG,
                    String.format("%s password listener attached to :%d", String.valueOf(et.getText()), et.getId()));

            if (et.getText().length() > 0 && !hasFocus) {
                loginForm.isPasswordValid(true);
            }
        };

        onFocusEmail = (v, hasFocus) -> {
            TextInputEditText et = (TextInputEditText) v;

            MyUtilsApp.showLog(LOG_TAG, "email listener attached");

            if (et.getText().length() > 0 && !hasFocus) {
                loginForm.isEmailValid(true);
            }
        };

    }



    public View.OnFocusChangeListener getOnFocusEmailChangeListener() {
        return onFocusEmail;
    }

    public View.OnFocusChangeListener getOnFocusPasswordChangeListener() {
        return onFocusPassword;
    }

    @BindingAdapter("onFocus")
    public static void bindFocusChange(TextInputEditText editText, View.OnFocusChangeListener onFocusChangeListener) {
        if (editText.getOnFocusChangeListener() == null) {
            editText.setOnFocusChangeListener(onFocusChangeListener);
        }
    }

}

public class LoginActivity extends AppCompatActivity {

    private static final String LOG_TAG = "LoginActivity";
    ActivityLoginBinding binding;
    private LoginRegisterViewModel loginRegisterViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_login);
        setupBindings(savedInstanceState);

    }


    private void setupBindings(Bundle savedInstanceState) {
        LoginFormViewModel loginFormViewModel = new ViewModelProvider(this).get(LoginFormViewModel.class);

        if(savedInstanceState==null)
            loginFormViewModel.init();

        binding.setLoginViewModel(loginFormViewModel);
        binding.setLifecycleOwner(this);

        loginFormViewModel.getLoginFields().observe(this, loginFields -> {
            Toast.makeText(LoginActivity.this,
                    "Email " + loginFields.getEmail() + ", Password " + loginFields.getPassword(),
                    Toast.LENGTH_SHORT).show();
        });

        binding.inLayoutLogin.btnLoginLogin.setOnClickListener(view -> {
            binding.executePendingBindings();
            loginFormViewModel.getLoginForm().onClick();

        });
    }

}
很明显,我已经将两个侦听器都设置为onFocusEmail类型,这只是因为onFocusPassword在运行时被附加到两个TextInputItems。 以下是日志:

com.example.increaseyouriq E/LoginFormViewModel:  password listener attached to :2131296499
com.example.increaseyouriq E/LoginFormViewModel: ttf password listener attached to :2131296499
onFocusEmail在任何地方都看不到,它已在运行时附加。
有关代码的更多详细信息,请参见

我对您的代码进行了一些实验,我相信我已经找到了根本原因

问题:

您的两个侦听器都没有附加到您的电子邮件字段(textinputtext“et_login_email”)

原因:

原因是这里有一个空检查

@BindingAdapter("onFocus")
public static void bindFocusChange(TextInputEditText editText, View.OnFocusChangeListener onFocusChangeListener) {
    if (editText.getOnFocusChangeListener() == null) {
        editText.setOnFocusChangeListener(onFocusChangeListener);
    }
}
并且您的电子邮件字段已经有一个onFocusChangeListener,它是由属性设置的

<com.google.android.material.textfield.TextInputLayout
    ...
    android:hint="@string/enter_email"
    ..."
    app:endIconMode="clear_text">