我正在使用安卓数据绑定库。 如果我想使视图可见,我可以写这样的东西:
<TextView
android:id="@+id/label_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@{habitListViewModel.message}"
app:visibility="@{habitListViewModel.hasError ? View.VISIBLE : View.GONE}" />
是否有选项以类似的 (xml) 方式绑定到 swipeRefreshLayout 的刷新属性?
目前,我正在通过调用setRefreshing(true/false)在代码中设置它,但希望将其在xml中保持一致。
无需破解。关键是在 SwipeRefreshLayout 文档中查找公共方法。通常,数据绑定将查找不带set
部分的相应名称。例如,您会在那里找到:
- setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener)
- setRefreshing(布尔刷新)
OnRefreshListener
由于 OnRefreshListener 是一个公共接口,因此使用单个方法,可以直接在绑定中使用它,如下所示:
app:onRefreshListener="@{() -> viewModel.onRefresh()}"
更新状态
对于此方法,您使用另一个公共方法,该方法转换为:
app:refreshing="@{viewModel.isLoading}"
总之,它可以看起来像这样:
<data>
<variable name="viewModel" type="ViewModel" />
</data>
<android.support.v4.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:refreshing="@{viewModel.isLoading}"
app:onRefreshListener="@{() -> viewModel.onRefresh()}">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
视图模型 - 科特林 :
class ViewModel(
private val provider: DataProvider
) : DataProvider.Callback {
/* isLoading - Needs to be public for Databinding! */
val isLoading = ObservableBoolean()
/* onRefresh() - Needs to be public for Databinding! */
fun onRefresh() {
isLoading.set(true)
provider.fetch(this)
}
fun onReady() = isLoading.set(false)
fun onError(oops: Exception) = isLoading.set(false)
}
视图模型 - Java:
public class ViewModel implements DataProvider.Callback {
public ObservableBoolean isLoading = new ObservableBoolean();
private DataProvider provider;
MasterViewModel(@NonNull final DataProvider provider) {
this.provider = provider;
}
/* Needs to be public for Databinding */
public void onRefresh() {
isLoading.set(true);
provider.fetch(this);
}
public void onReady(List results){
isLoading.set(false);
}
public void onError(Exception oops){
isLoading.set(false);
Log.e("Stack", oops);
}
}
更新:由于数据绑定从xml属性名称映射到set{AttributeName}
,因此您可以使用app:refreshing
,因为数据绑定将成功地将值提供给setRefreshing
SwipeRefreshLayout
方法(幸运的是,该方法存在并且是公共的):
<android.support.v4.widget.SwipeRefreshLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:refreshing="@{habitListViewModel.isLoading}">
...
//ListView,RecyclerView or something
</android.support.v4.widget.SwipeRefreshLayout>
就是这样!请注意,您可以简单地使用@{true}
或@{false}
而不是@{habitListViewModel.isLoading}
.希望有帮助。
确保已将binding.viewModel
设置为片段/活动中的当前实例。
这是我在片段中缺少的内容。
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
FragmentDiscoverMoviesBinding binding =
DataBindingUtil.inflate(inflater, R.layout.fragment_discover_movies, container, false);
viewModel = obtainViewModel(getActivity()); //get the viewmodel from the viewmodelFactory
binding.setViewModel(viewModel);
View rootView = binding.getRoot();
return rootView;
}
fragment_discover_movies.xml
<data>
<variable
name="viewModel"
type="com.ajdi.yassin.popularmovies.ui.movieslist.discover.DiscoverMoviesViewModel" />
</data>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:onRefreshListener="@{()-> viewModel.refresh()}"
app:refreshing="@{viewModel.isLoading}">
...
//ListView,RecyclerView or something
</android.support.v4.widget.SwipeRefreshLayout>
然后在视图模型中,定义刷新函数。
public class DiscoverMoviesViewModel extends ViewModel {
public MutableLiveData<Boolean> isLoading = new MutableLiveData<>(true);
.
.
.
public void refresh(){
isLoading.setValue(true);
//do your task
}
}
只需使用此app:refreshing="@{booleanValueHere}"
.数据绑定将自动检测回 isRefresh 函数的引用。