Google SignInButton的onClick无法使用DataBinding
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Google SignInButton的onClick无法使用DataBinding相关的知识,希望对你有一定的参考价值。
当我尝试在我的Google的onClick
中设置SignInButton
方法时:
android:onClick="@{() -> viewModel.onGoogleLoginClick()}"
我总是得到这个错误:
发现数据绑定错误。
**** /数据绑定错误**** msg:无法为android找到正确的回调类:onClick。试过android.view.View但它有0个抽象方法,应该有1个抽象方法。
file:/Users/user/Android/project/app/src/main/res/layout/activity_login.xml loc:53:31 - 53:66 **** data binding error ****
这是我的代码:
activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.login.LoginActivity">
<data>
<import type="android.view.View" />
<variable
name="viewModel"
type="com.example.myapp.ui.login.LoginViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="@dimen/default_layout_padding">
<EditText
android:id="@+id/login_name_editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/login_username_hint"
android:inputType="text"
android:text="@{viewModel.mEmail}" />
<EditText
android:id="@+id/login_pass_editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/login_name_editText"
android:hint="@string/login_password_hint"
android:inputType="numberPassword"
android:text="@{viewModel.mPassword}" />
<Button
android:id="@+id/login_login_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/login_pass_editText"
android:onClick="@{() -> viewModel.onServerLoginClick()}"
android:text="@string/login_login_button_text"
android:textAllCaps="true" />
<com.google.android.gms.common.SignInButton
android:id="@+id/login_google_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/login_login_button"
android:onClick="@{() -> viewModel.onGoogleLoginClick()}"/>
</RelativeLayout>
</layout>
LoginViewModel.class
public class LoginViewModel extends BaseViewModel<LoginNavigator> implements
GoogleApiClient.OnConnectionFailedListener, OnCompleteListener<GoogleSignInAccount>,
GoogleApiClient.ConnectionCallbacks {
private static final String LOG_TAG = LoginViewModel.class.getSimpleName();
public String mEmail;
public String mPassword;
public LoginViewModel(DataManager dataHelper, SchedulerProvider schedulerProviderHelper) {
super(dataHelper, schedulerProviderHelper);
}
public void onServerLoginClick() {
if (CommonUtils.loginDataIsCorrect(mEmail, mPassword)) {
doServerLogin(mEmail, mPassword);
} else {
getNavigator().handleError();
}
}
public void onGoogleLoginClick() {
getNavigator().googleLogin();
}
// Server
private void doServerLogin(String name, String pass) {
...
}
// Google
protected void doGoogleLogin(FragmentActivity fragmentActivity, Context context) {
...
}
...
}
LoginActivity.class
public class LoginActivity extends BaseActivity<ActivityLoginBinding, LoginViewModel> implements LoginNavigator {
private static final int REQUEST_CODE_REGISTER = 0;
private static final int REQUEST_CODE_GOOGLE_SIGN_IN = 1;
@BindString(R.string.login_data_missing_message)
String mDataMissingMessage;
@Inject
LoginViewModel mLoginViewModel;
private ActivityLoginBinding mActivityLoginBinding;
public static Intent newIntent(Context context) {
return new Intent(context, LoginActivity.class);
}
@Override
public int getBindingVariable() {
return BR.viewModel;
}
@Override
public int getLayoutId() {
return R.layout.activity_login;
}
@Override
public LoginViewModel getViewModel() {
return mLoginViewModel;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mActivityLoginBinding = getViewDataBinding();
mLoginViewModel.setNavigator(this);
mActivityLoginBinding.loginGoogleButton.setSize(SignInButton.SIZE_WIDE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_GOOGLE_SIGN_IN:
mLoginViewModel.handleGoogleSignInResult(data);
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public void googleLogin() {
mLoginViewModel.doGoogleLogin(this, this);
}
@Override
public void showGoogleForm(GoogleApiClient googleApiClient) {
Intent googleIntent = Auth.GoogleSignInApi.getSignInIntent(googleApiClient);
startActivityForResult(googleIntent, REQUEST_CODE_GOOGLE_SIGN_IN);
}
...
}
和BaseActivity.class,我绑定每个Activity
的视图和数据:
public abstract class BaseActivity<T extends ViewDataBinding, V extends BaseViewModel> extends AppCompatActivity {
private T mViewDataBinding;
private V mViewModel;
public abstract int getBindingVariable();
@LayoutRes
public abstract int getLayoutId();
public T getViewDataBinding() {
return mViewDataBinding;
}
public abstract V getViewModel();
public void performDependencyInjection() {
AndroidInjection.inject(this);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
performDependencyInjection();
super.onCreate(savedInstanceState);
performDataBinding();
}
@Override
protected void onResume() {
super.onResume();
}
private void performDataBinding() {
mViewDataBinding = DataBindingUtil.setContentView(this, getLayoutId());
this.mViewModel = mViewModel == null ? getViewModel() : mViewModel;
mViewDataBinding.setVariable(getBindingVariable(), mViewModel);
mViewDataBinding.executePendingBindings();
}
}
有谁知道为什么这个错误?因为SignInButton
实施OnClickListener
。我尝试过Invalidate Caches / Restart
并删除.gradle
和.idea
文件夹,但仍然无法正常工作。
这是一个有趣的问题,因为SignInButton扩展了View,但是doc明确指出在类中使用setOnClickListener(OnClickListener)注册一个监听器,而不是在xml中。数据绑定将lamda表达式包装为一个监听器(你可以在自动生成的数据绑定类中看到它),并且它可能不会坚持使用SignInButton所期望的监听器。例如。如果您尝试通过xml传递View.OnClickListener变量,则不应该得到编译错误,但您可能也无法接收您的点击事件(如文档中所述)。
幸运的是,我们有@BindingAdapter
解决类似的问题。这是Kotlin的一个例子:
BindingAdapters.kt
@BindingAdapter("android:onClick")
fun bindSignInClick(button: SignInButton, method: () -> Unit) {
button.setOnClickListener { method.invoke() }
}
layout.xml
<com.google.android.gms.common.SignInButton
...
android:onClick="@{() -> viewModel.onSignInClick()}" />
以上是关于Google SignInButton的onClick无法使用DataBinding的主要内容,如果未能解决你的问题,请参考以下文章
在 Android 中自定义 Google SignInButton
Google+ 登录按钮 [class='g-signin']
我想在点击 Google Plus 按钮时调用 Google Plus 回调函数