如何使用安卓数据绑定设置滑动刷新布局刷新属性?



我正在使用安卓数据绑定库。 如果我想使视图可见,我可以写这样的东西:

<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,因为数据绑定将成功地将值提供给setRefreshingSwipeRefreshLayout方法(幸运的是,该方法存在并且是公共的):

<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 函数的引用。

最新更新