我正在使用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中使它保持一致。
答案 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
}
}