简体   繁体   English

何时在 Android 数据绑定中评估表达式?

[英]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.使用 Android 数据绑定框架,我知道您可以传递一个 object 将baseObservable扩展为布局 xml,在 getter 上使用@Bindable相关部分并进行notifyPropertyChanged(BR.xxx)

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?我不明白的是:如果你不使用上面的大部分东西,只是直接在 xml 中调用 getter,什么时候会评估它?


Here's the code:这是代码:

my_widget.xml 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 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?如果someViewModel.name发生变化, testView的可见性会刷新吗?

  2. When does someViewModel.getName() get evaluated or how often? someViewModel.getName()什么时候评估或多久评估一次?

  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?如果表达式更复杂,例如: android:visibility="@{func(otherVariable, someViewModel.getName())? View.VISIBLE: View.GONE}" ,说otherVariable是上面数据部分中定义的另一个变量,如果不知何故otherVariable被重新设置,然后someViewModel.getName()将被评估并且testView将反映最新的可见性值,对吗?

  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?跟进问题 3,如果otherVariable更改为otherVariable.a ,其中a是“可绑定”字段,并且在 otherVariable 中调用notifyPropertyChanged(BR.a) otherVariable那么someViewModel.getName()也将重新评估,并且testView将反映最新的能见度值,对吗?

  5. Additionally, if I re-set someViewModel by calling binding.setSomeViewModel() but pass in the SAME someViewModel instance, does it do anything?此外,如果我通过调用 binding.setSomeViewModel binding.setSomeViewModel()重新设置someViewModel但传入相同的someViewModel实例,它会做任何事情吗? Will the expression get re-evaluated?表达式会被重新评估吗?

If someViewModel.name ever changes, does the testView's visibility refreshes?如果 someViewModel.name 发生变化,testView 的可见性会刷新吗?

it depends on the underlying technology you are using.这取决于您使用的底层技术。 LiveData?实时数据? Yes BaseObservable you have to manually notify that the observed property changed.是的 BaseObservable 您必须手动通知观察到的属性已更改。

When does someViewModel.getName() get evaluated or how often? someViewModel.getName() 什么时候评估或多久评估一次?

LiveData?实时数据? when you set/post a value.当您设置/发布一个值时。 BaseObservable when you notify it BaseObservable 当你通知它时

  1. Same as point 2与第 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.如果您更改观察到的 object 的实例,则不会。

I suggest you to create custom binding adapter for mutable visibility and use LiveData to update the visibility.我建议您为可变可见性创建自定义绑定适配器并使用 LiveData 来更新可见性。

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:要获取父活动,请创建 ActivityExtensions.kt 文件并在其中添加以下 function:

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:在 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:最后是layoutItem:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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