简体   繁体   中英

When does expression get evaluated in Android Data-binding?

With Android data-binding framework, I understand that you can pass an object that extends baseObservable to the layout xml, use @Bindable on getters and do notifyPropertyChanged(BR.xxx) to have the related part re-evaluated.

What I don't understand is this: if you don't use most the stuff above and just call the getter directly in xml, when would it be evaluated?


Here's the code:

my_widget.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="someViewModel"
            type="com.example.SomeViewModel" />
    </data>

    <androidx.cardview.widget.CardView>
        <View
            android:id="@+id/testView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="@{someViewModel.getName() ? View.VISIBLE : View.GONE}" />
    </androidx.cardview.widget.CardView>
</layout>

MyView.java

MyWidgetBinding binding = MyWidgetBinding.inflate(LayoutInflater.from(mContext), parent, false);
binding.setSomeViewModel(someViewModel);

Questions:

  1. If someViewModel.name ever changes, does the testView 's visibility refreshes?

  2. When does someViewModel.getName() get evaluated or how often?

  3. If the expression is more complicated, something like: android:visibility="@{func(otherVariable, someViewModel.getName())? View.VISIBLE: View.GONE}" , say otherVariable is another variable defined in data section above, if somehow otherVariable gets re-set, then someViewModel.getName() will get evaluated and testView will reflect the latest visibility value, correct?

  4. Following up on question 3, if otherVariable is changed to otherVariable.a where a is a 'bindable' field and notifyPropertyChanged(BR.a) is called in otherVariable then someViewModel.getName() will also get re-evaluated and testView will reflect the latest visibility value, correct?

  5. Additionally, if I re-set someViewModel by calling binding.setSomeViewModel() but pass in the SAME someViewModel instance, does it do anything? Will the expression get re-evaluated?

If someViewModel.name ever changes, does the testView's visibility refreshes?

it depends on the underlying technology you are using. LiveData? Yes BaseObservable you have to manually notify that the observed property changed.

When does someViewModel.getName() get evaluated or how often?

LiveData? when you set/post a value. BaseObservable when you notify it

  1. Same as point 2

  2. If you change the underlying value and notify this change properly, it will get propagated accordingly. If you change the instance of the observed object it will not.

I suggest you to create custom binding adapter for mutable visibility and use LiveData to update the visibility.

Code:

@BindingAdapter("mutableVisibility")
fun setMutableVisibility(view: View, visibility: MutableLiveData<Boolean>) {
    val parentActivity: AppCompatActivity? = view.getParentActivity()
    if (parentActivity != null) {
        visibility.observe(
                parentActivity,
                Observer { value -> if (value) view.visibility = View.VISIBLE
                else view.visibility = View.GONE})
    }
}

To get the parent activity create ActivityExtensions.kt file and add the following function in it:

fun View.getParentActivity(): AppCompatActivity?{
    var context = this.context
    while (context is ContextWrapper) {
        if (context is AppCompatActivity) {
            return context
        }
        context = context.baseContext
    }
    return null
}

And in the ViewModel:

//Other code here...
val itemVisibility = MutableLiveData<Boolean>()
//Other logic here to init itemVisible
if(itemVisibile) itemVisibility.value = true else itemVisibility.value = false

And finaly the layoutItem:

<View
     android:id="@+id/testView"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     app:mutableVisibility ="@{viewModel.itemVisibility}" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM