如何使用 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
,因为数据绑定将成功地将值提供给 SwipeRefreshLayout
的 setRefreshing
方法(这对我们来说幸运的是 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
部分的相应名称。例如。你会在那里找到:
- setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener)
- setRefreshing(boolean refreshing)
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
}
}
我正在使用 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
,因为数据绑定将成功地将值提供给 SwipeRefreshLayout
的 setRefreshing
方法(这对我们来说幸运的是 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
部分的相应名称。例如。你会在那里找到:
- setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener)
- setRefreshing(boolean refreshing)
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
}
}