我在使用Resource
包装数据时遇到了一个小问题,我不知道如何在数据绑定中使用它。
密封类:
sealed class Resource<out T: Any> {
data class Success<out T: Any>(val data: T): Resource<T>()
data class Error(val exception: Throwable): Resource<Nothing>()
object Loading: Resource<Nothing>()
}
我有这个val product: LiveData<Resource<NetworkProductDetails>>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewModel"
type="my.package.ProductDetailsViewModel" />
</data>
<TextView
android:id="@+id/product_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.product.productName}"
android:textAppearance="?attr/textAppearanceBody1"
android:gravity="center"/>
...
</layout>
我遇到了一个问题,因为viewModel.product
不是NetworkProductDetails
而是Resource<NetworkProductDetails>
,而且我的XML /数据绑定不知道如何处理。
我找到了一种工作方法,但我想知道是否还有一种更优雅的方法。
第一个解决方案:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewModel"
type="my.package.ProductDetailsViewModel" />
<variable
name="product"
type="my.package.NetworkProductDetails" />
</data>
<TextView
android:id="@+id/product_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{product.productName}"
android:textAppearance="?attr/textAppearanceBody1"
android:gravity="center"/>
...
</layout>
viewModel.product.observe(viewLifecycleOwner, Observer { it ->
when(it) {
is Resource.Success -> {
binding.product = it.data
}
}
}
第二个解决方案:
在我的评论中。
答案 0 :(得分:1)
我遇到了一个问题,因为viewModel.product不是NetworkProductDetails,而是Resource,而我的XML / Databinding不知道如何处理它。
您错过了data
。即使您以Resource.Success
结尾,productName
也不是Resource
甚至Resource.Success
的属性。 data
是Resource.Success
的属性,并且我假设productName
是NetworkProductDetails
的属性。您的表情没有data
。
您还需要教授有关其他两种情况(Loading
,Error
)以及如何处理的数据绑定。
在最佳情况下,您也许可以提取如下所示的绑定表达式:
android:text='@{viewModel.product instanceof Resource.Success ? viewModel.product.data.productName : "like, whatever"}'
但是:
我不知道instanceof
是否能很好地处理通用
我不知道您是否可以在一个表达式中两次引用LiveData
输出
或者,您可以尝试为Resource<NetworkProductDetails>
创建一个绑定适配器来处理这三种情况,尽管我从未尝试过使用泛型的类型。
答案 1 :(得分:0)
环顾四周后,我发现了2个解决方案,第一个是在我的原始帖子中,第二个是下面的解决方案:
在我的密封类中创建一个函数以暴露数据(如果它们是Success
,然后可以在我的xml
中使用它
优点:
BindingAdapter
Fragment
中添加更多代码缺点:
sealed class Resource<out T: Any> {
data class Success<out T: Any>(val data: T): Resource<T>()
data class Error(val exception: Throwable): Resource<Nothing>()
object Loading: Resource<Nothing>()
fun toData(): T? = if(this is Success) this.data else null
}
<TextView
android:id="@+id/product_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='@{viewModel.product.toData().productName}'
android:textAppearance="?attr/textAppearanceBody1"
android:gravity="center"/>