如何使用 android 数据绑定设置 SwipeRefreshLayout 刷新 属性?

How to set SwipeRefreshLayout refreshing property using android data binding?

我正在使用 android 数据绑定库。 如果我想让视图可见,我可以这样写:

<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 中使它保持一致。

更新: 由于数据绑定从 xml 属性名称映射到 set{AttributeName},您可以只使用 app:refreshing,因为数据绑定将成功地将值提供给 SwipeRefreshLayoutsetRefreshing 方法(这对我们来说幸运的是 public):

<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}。希望对您有所帮助。

就用这个app:refreshing="@{booleanValueHere}"。数据绑定将自动检测对 isRefreshing 函数的引用。

无需破解。关键是在SwipeRefreshLayout documentation中寻找public方法。一般来说,Databinding 会寻找没有 set 部分的相应名称。例如。你会在那里找到:

OnRefreshListener

由于 OnRefreshListener 是一个 public 接口,只有一个方法,您可以直接在绑定中使用它,如下所示:

app:onRefreshListener="@{() -> viewModel.onRefresh()}"

更新状态

对于这个,您使用另一种 public 方法,转换为:

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);
    }
}

确保您已将 binding.viewModel 设置为其在 fragment/Activity 中的当前实例。

这是我的案例中缺少的片段。

@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
        
        }
 }