【问题标题】:How to set SwipeRefreshLayout refreshing property using android data binding?如何使用 android 数据绑定设置 SwipeRefreshLayout 刷新属性?
【发布时间】:2017-04-19 00:57:43
【问题描述】:

我正在使用 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 中使其保持一致。

【问题讨论】:

    标签: android data-binding swiperefreshlayout android-layout


    【解决方案1】:

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

    <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 值设置为 true/false 时,swipeRefreshLayout 如何知道预期的行为?我不应该将它绑定到某个行为吗?它将如何将 app:refreshing 属性与其设置刷新行为的内部刷新字段联系起来?
    • 这就是为什么我称它为“小技巧”——这里的主要内容是,当您绑定到对象的属性时,Android DataBinding 只是在寻找对象的set{Name} 方法。这就是我们将自定义属性称为refreshing 的原因。因此,当您绑定到某个值时,它只会查找 SwipeRefreshLayout 对象的 setRefreshing 方法,我们的对象恰好包含该方法,因此行为将与您以编程方式调用 setRefreshing(true/false) 相同:)
    • 现在我明白了!聪明 :) 感谢您的额外解释!
    • 不客气:)这是一个不寻常的案例,所以必须有解释:)
    • 不需要attrs.xml,直接使用android:refreshing="@{habitListViewModel.isLoading}"
    【解决方案2】:

    只需使用此app:refreshing="@{booleanValueHere}"。数据绑定会自动检测对 isRefreshing 函数的引用。

    【讨论】:

    • @avlacatus 是的,它会自动检测到它
    【解决方案3】:

    无需破解。关键是在SwipeRefreshLayout documentation 中寻找公共方法。通常,Databinding 将查找没有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>
    

    viewmodel - kotlin:

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

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

    【讨论】:

    • 这就是你应该如何使用数据绑定库并且应该是公认的答案。
    • app:onRefreshListener 在我的情况下不调用方法 onRefresh。它只会让微调器旋转但不调用 onRefresh。它对你有用吗?
    • app:onRefreshListener 只设置监听器。要真正开始刷新,您需要触发事件。在此示例中,通过调用 isLoading.set(true) 完成
    • @Entreco 对我来说,当我向下滑动刷新时永远不会调用 onRefresh()。所以使用你的例子,我的问题是 provider.fetch(this) 永远不会被调用。
    • @user1795832 您必须将“viewModel”设置为您的片段(或活动)中的当前实例。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-29
      • 2017-12-07
      • 1970-01-01
      相关资源
      最近更新 更多