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

时间:2016-12-04 16:06:30

标签: android data-binding swiperefreshlayout android-layout

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

~/workspace/pset2/crack/ $ clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow bug.c -lcrypt -lcs50 -lm -o bug
~/workspace/pset2/crack/ $ ./bug
Segmentation fault

是否有以类似(xml)方式绑定到swipeRefreshLayout的刷新属性的选项?

目前我通过调用setRefreshing(true / false)在代码中设置它,但是希望在xml中使它保持一致。

5 个答案:

答案 0 :(得分:48)

无需破解。关键是在SwipeRefreshLayout documentation中寻找公共方法。通常,数据绑定将查找没有set部分的相应名称。例如。你会在那里找到:

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>

视图模型:

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

答案 1 :(得分:16)

<强>更新: 由于数据绑定从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}。希望有所帮助。

答案 2 :(得分:1)

只需使用此app:refreshing="@{booleanValueHere}"即可。数据绑定将自动检测返回isRefreshing函数的引用。

答案 3 :(得分:1)

我的声誉不足以发表评论,因此我将在此补充答案。

@Entreco是对的,没有必要使用attrs.xml。

我只想指出它无效因为我的ViewModel具有属性ObservableField<Boolean>

当我将其更改为ObservableBoolean时(就像在Entreco的例子中一样 - 感谢您),它有效。不过不确定原因。

答案 4 :(得分:1)

确保您已将 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
        
        }
 }