Java Android 数据绑定:更改属性时视图不会更新

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41913818/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:46:44  来源:igfitidea点击:

Android data binding : view does not update when property is changed

javaandroidobservableandroid-databinding

提问by

let me first start with showing the code:

让我首先从显示代码开始:

build.gradle (module):

build.gradle(模块):

android {
compileSdkVersion 24
buildToolsVersion "24.0.2"
dataBinding {
    enabled = true
}
defaultConfig {
    applicationId "com.example.oryaa.basecalculator"
    minSdkVersion 15
    targetSdkVersion 24
    versionCode 1
    versionName "1.0"
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}


dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.google.android.gms:play-services-appindexing:8.1.0'

activity_main.xml:

活动_main.xml:

<data>
    <import type="android.view.View" />
    <variable
        name="baseCalcModel"
        type="com.example.oryaa.basecalculator.BaseCalcModel">
    </variable>
</data>  <TextView
        android:id="@+id/resultOutput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/resultTextView"
        android:textColor="@color/DarkBlue"
        android:text="@{baseCalcModel.calcResult}"
        android:textSize="32dp" />

MainActicity.java:

MainActicity.java:

public class MainActivity extends AppCompatActivity {

EditText userInput = null;
TextView resultTV = null;
Spinner fromBaseSpinner = null;
Spinner toBaseSpinner = null;
ArrayList<String> spinnerArray = new ArrayList<>();
String _allowedChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String _onlyOnceChar = "-+*/";
BaseCalcModel baseCalcModel = new BaseCalcModel();

/**
 * ATTENTION: This was auto-generated to implement the App Indexing API.
 * See https://g.co/AppIndexing/AndroidStudio for more information.
 */
private GoogleApiClient client;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    binding.setBaseCalcModel(this.baseCalcModel);
    this.resultTV = (TextView) this.findViewById(R.id.resultOutput);
    this.fromBaseSpinner = (Spinner) findViewById(R.id.fromBaseSpinner);
    this.toBaseSpinner = (Spinner) findViewById(R.id.toBaseSpinner);
    this.userInput = (EditText) findViewById(R.id.userInput);
    SetupUI();
    baseCalcModel.setCalcResult("test");

    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.
    client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}

BaseCalcModel.java:

BaseCalcModel.java:

ublic class BaseCalcModel extends BaseObservable {


public String calcResult;
public BaseView firstNumView;
public BaseView secondNumView;
public BaseView resultNumView;
public int firstNumBase;
public int secondNumBase;
public int resultNumBase;
public String error;


@Bindable
String getCalcResult() {
    return calcResult;
}

@Bindable
public BaseView getFirstNumView() {
    return firstNumView;
}

@Bindable
public BaseView getSecondNumView() {
    return secondNumView;
}

@Bindable
public BaseView getResultNumView() {
    return this.resultNumView;
}

@Bindable
public int getFirstNumBase() {
    return this.firstNumBase;
}

@Bindable
public int getSecondNumBase() {
    return this.secondNumBase;
}

@Bindable
public int getResultNumBase() {
    return this.resultNumBase;
}

@Bindable
public String getError() {
    return this.error;
}

public void setCalcResult(String calcResult) {
    this.calcResult = calcResult;
    notifyPropertyChanged(com.example.oryaa.basecalculator.BR.calcResult);
}

public void setFirstNumView(BaseView firstNumView) {
    this.firstNumView = firstNumView;
    notifyPropertyChanged(com.example.oryaa.basecalculator.BR.firstNumView);
}

public void setSecondNumView(BaseView secondNumView) {
    this.secondNumView = secondNumView;
    notifyPropertyChanged(com.example.oryaa.basecalculator.BR.secondNumView);
}

public void setResultNumView(BaseView resultNumView) {
    this.resultNumView = resultNumView;
    notifyPropertyChanged(com.example.oryaa.basecalculator.BR.resultNumView);
}

public void setFirstNumBase(int firstNumBase) {
    this.firstNumBase = firstNumBase;
    notifyPropertyChanged(com.example.oryaa.basecalculator.BR.firstNumBase);
}

public void setSecondNumBase(int secondNumBase) {
    this.secondNumBase = secondNumBase;
    notifyPropertyChanged(com.example.oryaa.basecalculator.BR.secondNumBase);
}

public void setResultNumBase(int resultNumBase) {
    this.resultNumBase = resultNumBase;
    notifyPropertyChanged(com.example.oryaa.basecalculator.BR.resultNumBase);
}

public void setError(String error) {
    this.error = error;
    notifyPropertyChanged(com.example.oryaa.basecalculator.BR.error);
}


public BaseCalcModel() {
    firstNumView = new BaseView();
    secondNumView = new BaseView();
    resultNumView = new BaseView();
    firstNumBase = 0;
    secondNumBase = 0;
    resultNumBase = 0;
    calcResult = "";
    error = "";
}

public BaseCalcModel(BaseView firstNumView, BaseView secondNumView, BaseView resultNumView,
                     int firstNumBase, int secondNumBase, int resultNumBase, String clcResult,
                     String error) {
    this.firstNumView = firstNumView;
    this.secondNumView = secondNumView;
    this.resultNumView = resultNumView;
    this.firstNumBase = firstNumBase;
    this.secondNumBase = secondNumBase;
    this.resultNumBase = resultNumBase;
    this.calcResult = clcResult;
    this.error = error;
}

enter image description here

在此处输入图片说明

Im trying to do simple data binding, but my view doesn't updating after the proparty is changing. as you can see in the image, my code arriving to:

我正在尝试进行简单的数据绑定,但是在 proparty 更改后我的视图没有更新。正如您在图像中看到的,我的代码到达:

            notifyPropertyChanged(com.example.oryaa.basecalculator.BR.calcResult);

but the view is updating only when the app started or when I'm rotating my phone for vertical to horizontal or vice versa.

但是视图仅在应用程序启动时或当我将手机从垂直方向旋转到水平方向时才会更新,反之亦然。

Where is my problem?

我的问题在哪里?

Thanks a lot, Or Yaacov

非常感谢,或者 Yaacov

回答by XIII-th

You need to call executePendingBindings()for immediately update binding value in view:

您需要executePendingBindings()在视图中立即调用更新绑定值:

When a variable or observable changes, the binding will be scheduled to change before the next frame. There are times, however, when binding must be executed immediately. To force execution, use the executePendingBindings() method.

当变量或 observable 发生变化时,绑定将被安排在下一帧之前发生变化。但是,有时必须立即执行绑定。要强制执行,请使用 executePendingBindings() 方法。

Look at Advanced Bindingchapter for more info

查看高级绑定章节了解更多信息

回答by Khemraj

  • Make your model class fields private.
  • Change getCalcResult()should be public.
  • BaseViewshould be extending BaseObservable
  • If you don't change model value dynamically. Then you need not to make every accessor @Bindable. You can remove that. And also remove notifyPropertyChanged(). Opposite of this if you need to change model values dynamically then use @Bindableattribute.
  • 将您的模型类字段设为私有。
  • 改变getCalcResult()应该是公开的。
  • BaseView应该延长 BaseObservable
  • 如果您不动态更改模型值。那么你不需要制作每个访问器@Bindable。你可以删除它。并且还删除notifyPropertyChanged(). 相反,如果您需要动态更改模型值,则使用@Bindable属性。

You are good to go.

你已准备好出发。

public class BaseCalcModel extends BaseObservable {
private String calcResult;
private BaseView firstNumView;
private BaseView secondNumView;
private BaseView resultNumView;
private int firstNumBase;
private int secondNumBase;
private int resultNumBase;
private String error;

public String getCalcResult() {
    return calcResult;
}

public void setCalcResult(String calcResult) {
    this.calcResult = calcResult;
}

public BaseView getFirstNumView() {
    return firstNumView;
}

public void setFirstNumView(BaseView firstNumView) {
    this.firstNumView = firstNumView;
}

public BaseView getSecondNumView() {
    return secondNumView;
}

public void setSecondNumView(BaseView secondNumView) {
    this.secondNumView = secondNumView;
}

public BaseView getResultNumView() {
    return resultNumView;
}

public void setResultNumView(BaseView resultNumView) {
    this.resultNumView = resultNumView;
}

public int getFirstNumBase() {
    return firstNumBase;
}

public void setFirstNumBase(int firstNumBase) {
    this.firstNumBase = firstNumBase;
}

public int getSecondNumBase() {
    return secondNumBase;
}

public void setSecondNumBase(int secondNumBase) {
    this.secondNumBase = secondNumBase;
}

public int getResultNumBase() {
    return resultNumBase;
}

public void setResultNumBase(int resultNumBase) {
    this.resultNumBase = resultNumBase;
}

public String getError() {
    return error;
}

public void setError(String error) {
    this.error = error;
}

}

}

回答by uan

I had a similar issue when I needed to refresh the views after an event, with my variable objects not observable, so I added this:

当我需要在事件发生后刷新视图时遇到了类似的问题,我的变量对象不可观察,所以我添加了这个:

binding?.invalidateAll()

I hope it helps.

我希望它有帮助。

回答by dgngulcan

In case you might be experiencing this issue with LiveData, you might've forgotten to add binding.setLifecycleOwner(lifecycleOwner).

如果您在使用 时可能遇到此问题LiveData,您可能忘记添加binding.setLifecycleOwner(lifecycleOwner).

回答by nAkhmedov

Please make sure you are updating the same object fieldwhen data binding does not work on you. The object's instancemust be the same in order to update UI. Maybe my answer helps to someone, enjoy coding!

the same object field当数据绑定对您不起作用时,请确保您正在更新。The object's instance必须相同才能更新 UI。也许我的回答对某人有所帮助,享受编码!