Google SignInButton 的 onClick 无法使用数据绑定

2024-01-03

当我尝试设置onClick我的 Google 中的方法SignInButton:

android:onClick="@{() -> viewModel.onGoogleLoginClick()}"

我总是收到这个错误:

发现数据绑定错误。

****/ 数据绑定错误 ****msg: 找不到 android:onClick 的正确回调类。尝试了 android.view.View 但它有 0 个摘要 方法,应该有1个抽象方法。

文件:/Users/user/Android/project/app/src/main/res/layout/activity_login.xml loc:53:31 - 53:66 ****\ 数据绑定错误 ****

这是我的代码:

活动登录.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) {
        ...
    }
    ...
}

登录活动.类

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);
    }
    ...
}

And the 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 and .idea文件夹,但仍然无法正常工作。


幸运的是,我们有@BindingAdapter来解决类似的问题。这是 Kotlin 中的一个示例:

绑定适配器.kt

@BindingAdapter("android:onClick")
fun bindSignInClick(button: SignInButton, method: () -> Unit) {
    button.setOnClickListener { method.invoke() }
}

布局.xml

<com.google.android.gms.common.SignInButton
            ...
            android:onClick="@{() -> viewModel.onSignInClick()}" />
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Google SignInButton 的 onClick 无法使用数据绑定 的相关文章

随机推荐

  • 使用现有的 pptx 创建新的 pptx Python-Pptx

    我正在尝试使用 old pptx 创建 new pptx old pptx 有 4 张幻灯片 我想在 4 张幻灯片中创建内容几乎相同的 new pptx 仅进行少量文本修改 我跳过了下面代码中的修改部分 您可以举个例子 例如将小写字母转换为
  • 导入 shapefile 外部的遮罩区域(底图/matplotlib)

    我正在通过 Matplotlib 在美国和加拿大东海岸的底图上绘制数据 除了基础层 填充的等值线图 之外 我还使用 Matplotlib 的 readshapefile 工具将此焦点区域的 shapefile 覆盖在数据之上 我想知道如何屏
  • 将蛋糕脚本中的警告消息记录在文本文件中

    我正在使用下面的蛋糕脚本来编译我的C 项目 中显示的警告消息很少PowerShell执行脚本时 我喜欢将警告记录在物理位置的文本文件中 例如 D WarningReport txt 下面是我用来编译项目的蛋糕脚本任务 Task Build
  • 使用JNI而不是JNA调用本机代码?

    与 JNI 相比 JNA 似乎更容易用来调用本机代码 在什么情况下您会使用 JNI 而不是 JNA JNA 不支持 C 类的映射 因此如果您使用 C 库 则需要 jni 包装器 如果你需要大量的内存复制 例如 您调用一个方法 该方法返回一个
  • 在 Pygame 上播放 midi

    好的 这就是我得到的 import pygame import sys from pygame locals import bif bg jpg mif pkmn png sif bubble png song 1 testaudio mi
  • base64 解码的文件不等于原始未编码的文件

    我有一个普通的pdf文件 A pdf 第三方以base64对该文件进行编码 并将其作为长字符串在网络服务中发送给我 我无法控制第三方 我的问题是 当我使用 java org apache commons codec binary Base6
  • 什么是好的、众所周知的 JavaScript MVC 模式?

    在 ASP NET MVC 应用程序中管理 JavaScript 文件和函数 对象上下文的最佳方法是什么 谷歌说http javascriptmvc com http javascriptmvc com
  • 在 Quartz 作业中使用 CDI

    我想知道是否可以在 Quartz 作业中以可移植的方式使用 CDI bean 我已经尝试编写自己的 JobFactory 等 但问题是 BeanManager 无法通过 JNDI 使用 因为作业在非托管线程中运行 我的应用程序服务器是 We
  • React组件的render函数中返回DOM元素

    我有一个外部库 可以呈现一些自定义 js 控件 该库返回一个可以插入到页面中的 DOM 元素 我正在 React 中为这个库创建包装器 我已经将所有内容都连接起来 但我不确定如何允许渲染函数接受 DOM 元素作为其返回 render if
  • 如何在 HtmlAgilityPack 中按类获取元素

    你好 我制作 HttpWebResponse 并获取包含我需要的所有数据的 Html 页面 例如带有日期信息的表 我需要将它们保存到数组列表并将其保存到 xml 文件 html 页面示例 table tr td class padding5
  • 如何在 元素内创建标签?

    我想在输入元素内插入描述性文本 当用户单击它时该描述性文本就会消失 我知道这是一个很常见的技巧 但我不知道该怎么做 最简单 更好的解决方案是什么 如果您使用的是 HTML5 则可以使用placeholder属性
  • 这是什么样的排序?

    假设我有一个整数列表 其中每个元素都是 1 到 20 之间的数字 这不是我要排序的内容 现在 我有一个 操作 数组 其中每个操作 Removes列表中的某些 已知 数字 and Adds列表中的某些其他 已知 号码 and如果列表在操作开始
  • 使用 Underscore JS 对 JSON 数组进行分组和聚合

    我有一个 json 数组对象 我想根据 FlexCategoryName 列对数据进行分组 并对矩阵列执行聚合 例如 成本 平均值 点击 总和等 下面是 JSON 数组对象 Array 100 0 Object 1 Object 2 Obj
  • 我将如何计算数组中每个字母数字的数量? (美国PL)

    我不知道如何获取矩阵并计算每行的字母数字值的数量 我只会采用具有我正在计算的值的矩阵 例如 如果我得到 ABA455 7L9O36G DZLFPEI 第一行我会得到类似 A 2 B 1 4 1 5 2 的内容 并且每一行都会独立计数 如果您
  • 带片段的 ViewPager - onPause()、onResume()?

    使用时ViewPager带着碎片 我们的onPause onResume在选项卡之间移动时不会调用方法 有没有什么方法可以让我们在片段中弄清楚我们何时变得可见或隐藏 不幸的是我有逻辑onResume onPause 就像注册位置服务一样 切
  • 在深度嵌套的字典中查找键

    我有很多嵌套字典 我试图找到嵌套在某处的某个键 例如这个钥匙叫做 水果 我如何找到这个键的值 H vard 的递归解决方案可能会没问题 除非嵌套级别太高 然后你会得到一个RuntimeError maximum recursion dept
  • 我可以使用一个控制器更新 AngularJS 中的两个视图吗?

    是否可以将两个视图绑定到一个控制器 以便无论数据在何处 视图1 视图2或模型中 发生更改 两个视图都会更新 它应该像这个例子一样工作 消除混乱
  • Python函数的参数长度? [复制]

    这个问题在这里已经有答案了 可能的重复 如何找出Python中方法的数量 https stackoverflow com questions 990016 how to find out the arity of a method in p
  • RabbitMQ:如何在标头交换中使用复杂表达式?

    下面是死信队列中消息的标头 我正在使用 RabbitMQ TypeId com example queue TesteDTO correlationId dfbc9457 8de6 9b77 b7ad b259d1e2ede4 sequen
  • Google SignInButton 的 onClick 无法使用数据绑定

    当我尝试设置onClick我的 Google 中的方法SignInButton android onClick gt viewModel onGoogleLoginClick 我总是收到这个错误 发现数据绑定错误 数据绑定错误 msg 找不