问题
I'm trying to achieve one simple view hide/show using data binding. I have an api call and I have to show one progressbar while the api call is going on. Once I get the response have to dismiss this progress and display the data. I tried to change the visibility of progressbar dynamically using data binding. But nothing happens. Only for the first time the progresbar visibility is set according to the binding variable. its not dynamically updating as I update the binding variable.
following is my sample code for the same
Activity:
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
final ViewModel viewmodel = new ViewModel();
binding.setViewmodel(viewmodel);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
loadData(viewmodel);
}
});
}
private void loadData(final ViewModel viewmodel) {
viewmodel.setLoading(true);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "Loading finished");
viewmodel.setLoading(false);
}
}, 2000);
}
}
ViewModel:
import android.databinding.BaseObservable;
import android.databinding.Bindable;
public class ViewModel extends BaseObservable {
private boolean isLoading;
private String data;
@Bindable
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
@Bindable
public boolean isLoading() {
return isLoading;
}
public void setLoading(boolean loading) {
isLoading = loading;
}
}
activity_main.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">
<data>
<import type="android.view.View"/>
<variable name="viewmodel" type="com.test.databindnig.ViewModel"/>
</data>
<LinearLayout
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.test.databindnig.MainActivity">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="@{viewmodel.isLoading ? View.VISIBLE : View.GONE}"/>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewmodel.data}"
android:visibility="@{viewmodel.isLoading ? View.GONE : View.VISIBLE}"/>
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Load data"/>
</LinearLayout>
</layout>
and also in the app's build.gradle
dataBinding {
enabled = true
}
What is missing over here? why doesn't it work? Thanks in advance..
回答1:
you need to notify that your property value is changed, try this
public void setLoading(boolean loading) {
isLoading = loading;
notifyPropertyChanged(BR._all);
}
or if you want to notify it just for single variable, use BR.propertyName
notifyPropertyChanged(BR.loading);
回答2:
I want to clarify that if you use notifyPropertyChanged(BR._all);
, it will notify all observables unnecessarily.
You should use notifyPropertyChanged(BR.field);
instead to notify only changed item.
If you want model.setLoading(true)
. It will refract on related views from this field.
Note that your accessor should be annotated with @Bindable
attribute. Otherwise BR
class will not have your field name.
@Bindable
public boolean isLoading() {
return isLoading;
}
public void setLoading(boolean isLoading ) {
this.isLoading = isLoading ;
notifyPropertyChanged(BR.isLoading );
}
回答3:
add
<import type="android.view.View" />
on top of your XMl file result solution will be like following
<data>
<import type="android.view.View" />
<variable
name="obj"
type="com.you.modal.class" />
</data>
<import type="android.view.View" />
来源:https://stackoverflow.com/questions/40858770/how-to-dynamically-change-view-visibility-using-android-data-binding