Android data binding : view does not update when property is changed
Solution 1
In case you might be experiencing this issue with LiveData
, you might've forgotten to set lifecycle owner of your binding;
binding.setLifecycleOwner(lifecycleOwner)
Solution 2
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.
Solution 3
You need to call executePendingBindings()
for immediately update binding value in view:
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.
Look at Advanced Binding chapter for more info
Solution 4
- Make your model class fields private.
- Change
getCalcResult()
should be public. BaseView
should be extendingBaseObservable
- If you don't change model value dynamically. Then you need not to make every accessor
@Bindable
. You can remove that. And also removenotifyPropertyChanged()
. Opposite of this if you need to change model values dynamically then use@Bindable
attribute.
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;
}
}
Solution 5
I had the exact same problem. Apparently it was a single line that had been causing the issue. All you have to do is set the licycleowner
to the binding
.
binding.lifecycleOwner = this
Related videos on Youtube
Jack Guo
Updated on July 09, 2022Comments
-
Jack Guo almost 2 years
let me first start with showing the code:
build.gradle (module):
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:
<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:
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:
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; }
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:
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
-
GvSharma over 7 yearsremove this line from MainActivity() "setContentView(R.layout.activity_main);" And try again
-
Admin over 7 yearsNo, still doesn't work
-
George Mount over 7 yearsTry making the fields private. It may be preferring to access the fields over the accessor methods.
-
Kirill Kulakov over 7 yearsWhy is your DTO holds on to a
BaseView
? I doubt it's related to the issue, but it sounds like really bad practice -
Admin over 7 years@GeorgeMount If I'm changing all the fields to private I'm getting the next compelation error: Error:(14, 52) error: package com.example.oryaa.basecalculator.databinding does not exist Error:Execution failed for task ':app:compileDebugJavaWithJavac'. > java.lang.RuntimeException: Found data binding errors. ****/ data binding error ****msg:Could not find accessor com.example.oryaa.basecalculator.BaseCalcModel.calcResult file:...\activity_main.xml loc:78:28 - 78:51 ****\ data binding error **** and KirillKulakov BaseView is an self made object that contains 4 Strings.
-
George Mount over 7 yearsYes, getCalcResult() must be public.
-
-
Alif Hasnain over 4 yearsis this the optimal solution?
-
oxied about 4 years
invalidateAll
works for me.executePendingBindings
doesn't. -
Serdar Samancıoğlu over 3 yearsFor me, this was the case. Thank you!
-
Panos Gr over 3 years
binding?.invalidateAll()
causes weird layout problems and should be avoided. Prefer to useLiveData
orObservableField
s to wrap your data and pass it into your bindings if your data needs to handle change of state. -
Andrew almost 3 yearsWhere exactly do we but this, if we use databinding inside a fragment????
-
Sergei Bubenshchikov almost 3 years@Andrew you can call this method when your data updated (when you bind data to view holder for example)
-
UnknownDeveloper over 2 yearsWhy did something like this happen?