【问题标题】:Two-Way databinding in EditTextEditText 中的双向数据绑定
【发布时间】:2016-12-23 06:48:08
【问题描述】:

我有这个对象

ObservableInt someNumber;

public ObservableInt getSomeNumber()
{
    return someNumber;
}

public void setSomeNumber(ObservableInt number)
{
    this.someNumber = number;
}

而我的 AppCompatEditText 在 xml 代码中是这样的:

<android.support.v7.widget.AppCompatEditText
        android:layout_width="0dp"
        android:layout_height="@dimen/agro_item_height"
        android:layout_weight="1"
        android:inputType="numberDecimal"
        android:text="@={String.valueOf(myObject.someNumber)}"
        android:gravity="center_horizontal"/>

我遇到了这个错误:

Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
java.lang.RuntimeException: failure, see logs for details.
cannot generate view binders java.lang.NullPointerException
at android.databinding.tool.expr.MethodCallExpr.generateCode(MethodCallExpr.java:69)
at android.databinding.tool.expr.Expr.toFullCode(Expr.java:745)
at android.databinding.tool.expr.Expr.assertIsInvertible(Expr.java:767)
at android.databinding.tool.BindingTarget.addInverseBinding(BindingTarget.java:68)
at android.databinding.tool.LayoutBinder.<init>(LayoutBinder.java:228)
at android.databinding.tool.DataBinder.<init>(DataBinder.java:52)
at android.databinding.tool.CompilerChef.ensureDataBinder(CompilerChef.java:83)
at android.databinding.tool.CompilerChef.sealModels(CompilerChef.java:168)
at android.databinding.annotationprocessor.ProcessExpressions.writeResourceBundle(ProcessExpressions.java:149)
at android.databinding.annotationprocessor.ProcessExpressions.onHandleStep(ProcessExpressions.java:82)
at android.databinding.annotationprocessor.ProcessDataBinding$ProcessingStep.runStep(ProcessDataBinding.java:154)
at android.databinding.annotationprocessor.ProcessDataBinding$ProcessingStep.access$000(ProcessDataBinding.java:139)
at android.databinding.annotationprocessor.ProcessDataBinding.process(ProcessDataBinding.java:66)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
at com.sun.tools.javac.main.Main.compile(Main.java:523)
at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:46)
at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:33)
at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:104)
at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:53)
at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:38)
at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:35)
at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:25)
at org.gradle.api.tasks.compile.JavaCompile.performCompilation(JavaCompile.java:163)
at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:145)
at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:93)
at com.android.build.gradle.tasks.factory.AndroidJavaCompile.compile(AndroidJavaCompile.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(AnnotationProcessingTaskFactory.java:245)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:221)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(AnnotationProcessingTaskFactory.java:232)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:210)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:66)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:153)
at org.gradle.internal.Factories$1.create(Factories.java:22)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:53)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:150)
at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:98)
at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:92)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:63)
at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:92)
at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:83)
at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:99)
at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:46)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:58)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:48)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:30)
at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:81)
at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:46)
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
at org.gradle.util.Swapper.swap(Swapper.java:38)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:237)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

我已经试过了

android:text="@={myObject.someNumber}"

但我遇到了这个错误:

Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
java.lang.RuntimeException: Found data binding errors.
****/ data binding error ****msg:Cannot find the getter for attribute     'android:text' with value type int on android.support.v7.widget.AppCompatEditText.
file:C:\Users\Moviit\AndroidStudioProjects\pbbchile-android\app\src\main\res\layout\row_agro_tab.xml
loc:51:8 - 60:48
****\ data binding error ****

任何人都有如何做到这一点的例子?

【问题讨论】:

  • 您的第一个表达式将不起作用,因为没有反向表达式。您的第二个表达式将不起作用,因为 Android 会将其视为字符串资源。我的猜测是您需要将视图模型切换为使用 ObservableField&lt;String&gt; 而不是 ObservableInt

标签: android android-databinding


【解决方案1】:

您可以在 EditText 上进行双向绑定。

使用单向数据绑定,您可以在属性上设置值并 设置一个对该属性的变化做出反应的监听器

变量为字符串类型

<android.support.v7.widget.AppCompatEditText
    ...
    android:text="@={model.someString}"
    />

变量是数字

<android.support.v7.widget.AppCompatEditText
    ...
    android:text="@={`` + model.someNumber}"
    />

``两个后撇号自动绑定

  • 在 EditText 上设置时将数字转换为字符串
  • 在模型中设置时将字符串文本转换为数字

提示

documentation 可以看到,双向绑定可以用于多种用途。

  1. 复选框、单选按钮、开关、切换按钮

android:checked="@={model.checked}"

  1. 无线电组 - android:checkedButton

android:checkedButton="@={model.selectedId}"

  1. 评分栏 - android:rating

android:rating="@={model.rating}"

等等

【讨论】:

【解决方案2】:

有一个未发表的简单原始转换技巧:

<android.support.v7.widget.AppCompatEditText
    android:layout_width="0dp"
    android:layout_height="@dimen/agro_item_height"
    android:layout_weight="1"
    android:inputType="numberDecimal"
    android:text="@={`` + myObject.someNumber}"
    android:gravity="center_horizontal"/>

我相信它只是在 Android Studio 2.2 中添加的。

【讨论】:

  • 它抛出这个错误:错误:任务':app:compileDebugJavaWithJavac'的执行失败。 > java.lang.RuntimeException:发现数据绑定错误。 ****/ 数据绑定错误 ****msg:无法反转表达式 ("") + (dosisAgrochemical):双向绑定不支持字符串连接运算符 (+)。文件:C:\Users\Moviit\AndroidStudioProjects\pbbchile-android\app\src\main\res\layout\item_agro_dosis.xml loc:23:29 - 23:51 ****\ 数据绑定错误 ****
  • 抱歉,2.2中一定不能发布。我想它必须等待2.3。
  • 它不允许清除所有值并输入新值。保留最后一位
  • 你能帮我解决这个问题吗:stackoverflow.com/questions/64596538/… 谢谢。
【解决方案3】:

我尝试使用@George Mount 提到的自定义设置器(https://medium.com/google-developers/android-data-binding-custom-setters-55a25a7aea47#.vsry4d95w),并受到这个答案的启发(Android two way binding with Integer type causes databinding does not exist

您仍然可以使用原始代码进行双向绑定。

模型类

public class Age {
    private ObservableInt someNumber;
    private ObservableField<String> someStr;
    public Age() {
        someNumber = new ObservableInt();
        someStr = new ObservableField<>();
    }
    public ObservableInt getSomeNumber() {
        return someNumber;
    }
    public void setSomeNumber(ObservableInt pSomeNumber) {
        someNumber.set(pSomeNumber.get());
    }
    public ObservableField<String> getSomeStr() {
        return someStr;
    }
    public void setSomeStr(ObservableField<String> pSomeStr) {
        someStr.set(pSomeStr.get());
    }
}

属性的自定义setter和getter

@BindingAdapter("android:text")
public static void bindIntegerInText(AppCompatEditText tv, int value) {
    tv.setText(String.valueOf(value));
}
@InverseBindingAdapter(attribute = "android:text")
public static int getIntegerFromBinding(TextView view) {
    return Integer.parseInt(view.getText().toString());
}

活动中的代码

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityMain2Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_main2);
    mAge = new Age();
    mAge.setSomeNumber(new ObservableInt(3));
    mAge.setSomeStr(new ObservableField<>("Test"));
    binding.setAge(mAge);
    binding.btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mAge.setSomeNumber(new ObservableInt(4));
            mAge.setSomeStr(new ObservableField<>("Hello World"));
        }
    });
}

我用 xml 中的 ObservableInt、Observable、普通字符串资源和绑定字符串资源做了 4 个演示。

<string name="helloworld">Hello World</string>

activity_main3.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"

    >

    <data>

        <variable
            name="age"
            type="example.com.testerapplication.Age"/>
    </data>

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

        <android.support.v7.widget.AppCompatEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={age.someNumber}"/>

        <android.support.v7.widget.AppCompatEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={age.someStr}"/>

        <android.support.v7.widget.AppCompatEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/helloworld"/>

        <android.support.v7.widget.AppCompatEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{@string/helloworld}"/>

        <Button
            android:id="@+id/btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Test"
            />
    </LinearLayout>

</layout>

【讨论】:

  • 非常感谢您的解决方案,但它给了我一个错误。 EditText 从 0 值开始,但是当您删除它时,错误: Invalid int: "" 因为 BindingAdapter 试图解析 "" 值。您对此有解决方案吗?
【解决方案4】:

感谢@LongRanger 的绑定适配器,我能够在我的解决方案中取得更多进步,但我不得不对适配器和我的代码进行一些更改。首先,我必须像这样初始化 ObservableInt 成员:

ObservableInt someNumber;

public ObservableInt getSomeNumber()
{
    return someNumber;
}

public void setSomeNumber(ObservableInt number)
{
    this.someNumber = number;
}

其次,我必须将@LongRanger 提供的适配器更改为:

@BindingAdapter("android:text")
public static void bindIntegerInText(AppCompatEditText tv, int value)
{
    tv.setText(String.valueOf(value));    

    // Set the cursor to the end of the text
    tv.setSelection(tv.getText().length());
}

@InverseBindingAdapter(attribute = "android:text")
public static int getIntegerFromBinding(TextView view)
{
    String string = view.getText().toString();

    return string.isEmpty() ? 0 : Integer.parseInt(string);
}

这样我可以避免错误:Invalid int "",当尝试在 @InverseBindingAdapter 上执行 Integer.parse(...) 时。在此之后,我必须将光标放在带有@BindingAdapter 的 EditText 的末尾,否则光标会一直移动到开头。

【讨论】:

  • InverseBindingAdapter 会影响其他需要绑定到 String 的绑定吗?
  • 是的@gopalanrc,每次你在“android:text”标签中有类似“@={myObject.someNumber}”的绑定和反向绑定适配器都会工作
  • @DanPonce 在这个答案中有两个问题:1)如果你设置了一个 Observable 变量( android:text = "@{Observable}" )那么 bindIntegerInText 将被插入到无限循环中,所以你应该检查新变量是否与新变量不同。 (参考:developer.android.com/topic/libraries/data-binding/…) 2)如果你想修改例如在字符串中间的文本(“abc(here)dfgh”),当你开始在中间写新字符时,光标将移动到末尾字符串
【解决方案5】:

@CommonsWare 是对的,你应该使用ObservableField&lt;Str‌​ing&gt; 而不是ObservableInt。如果你真的需要它作为数字,只需解析它Integer.valueOf(stringNumber)

public ObservableField<Str‌​ing> someNumber;

//and in xml code:

<EditText
        android:layout_width="0dp"
        android:layout_height="@dimen/agro_item_height"
        android:layout_weight="1"
        android:inputType="numberDecimal"
        android:text="@={myObject.someNumber}"
        android:gravity="center_horizontal"/>

EDITED:或者,如上所述,编写自定义 @InverseBindingAdapter

public class MyEditTextBindingAdapters {

    @BindingConversion
    public static String intToStr(Integer value) {
        return value != null ? String.valueOf(value) : "";
    }

    @InverseBindingAdapter(attribute = "android:text")
    public static Integer captureIntValue(EditText view) {
        long value = 0;
        try {
            value = Integer.parseInt(view.getText().toString());
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        return value;
    }
}

【讨论】:

    【解决方案6】:

    只需这样做:

    android:text="@={user.username}"
    

    完整代码:

     <EditText
                android:id="@+id/username"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="user name"
                android:text="@={user.username}"/>
    

    和用户类

    public class User {
    public ObservableField<String> username = new ObservableField<>();
    public ObservableField<String> password = new ObservableField<>();
    
    public User() {
        this("", "");
    }
    
    public User(String username, String password) {
        this.username.set(username);
        this.password.set(password);
    }
    

    【讨论】:

    • 我想要做的是在我的 EditText 上使用带有两种方式绑定的 ObservableInt。我对字符串没有问题
    猜你喜欢
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多