CommonPullToRefresh是一个开源的支持上拉刷新下拉加载更多的控件的库
附上原作者介绍:
在android-Ultra-Pull-To-Refresh的基础上增加了加载更多的支持,感谢作者
- 下拉刷新支持大部分
view
:ListView
、ScrollView
、WebView
等,甚至一个单独的TextView
- 加载更多目前支持
ListView
、RecyclerView
、GridView
、SwipeRefreshLayout
- 支持自定义header以及footer
- 增加SwipeRefreshLayout刷新方式,同样支持加载更多
github地址:https://github.com/Chanven/CommonPullToRefresh
但是在SwipeRefreshLayout嵌套RecyclerView,配合SwipeRefreshHelper使用的时候编译版本太高(本人测试时27的)会报异常:IllegalStateException :unSupported contentView
定位发现是SwipeRefreshHelper里的
setLoadMoreEnable()
方法里抛的异常:
if (null == mLoadMoreHandler) {
if (mContentView instanceof GridView) {
mLoadMoreHandler = new GridViewHandler();
} else if (mContentView instanceof AbsListView) {
mLoadMoreHandler = new ListViewHandler();
} else if (mContentView instanceof RecyclerView) {
mLoadMoreHandler = new RecyclerViewHandler();
}
}
if (null == mLoadMoreHandler) {
throw new IllegalStateException("unSupported contentView !");
}
这就很纠结了,我的mContentView 是Recyclerview没错,为什么mLoadMoreHandler还是null呢??
原因在SwipeRefreshHelper的构造函数里:
public SwipeRefreshHelper(SwipeRefreshLayout refreshLayout) {
this.mSwipeRefreshLayout = refreshLayout;
init();
}
继续点进init()方法里:
private void init() {
if (mSwipeRefreshLayout.getChildCount() <= 0) {
throw new RuntimeException("SwipRefreshLayout has no child view");
}
try {
Field field = mSwipeRefreshLayout.getClass().getDeclaredField("mTarget");
field.setAccessible(true);
mContentView = (View) field.get(mSwipeRefreshLayout);
} catch (Exception e) {
e.printStackTrace();
}
}
实际上,这里
Field field = mSwipeRefreshLayout.getClass().getDeclaredField("mTarget");
反射获取并没有获取到SwipeRefreshLayout里的私有变量mTarget,具体原因可以查看SwipeRefreshLayout的源码,
解决方案:
重写下init方法:
private void init() {
if (mSwipeRefreshLayout.getChildCount() <= 0) {
throw new RuntimeException("SwipRefreshLayout has no child view");
}
mSwipeRefreshLayout.post(() -> {
try {
Field field = mSwipeRefreshLayout.getClass().getDeclaredField("mTarget");
field.setAccessible(true);
mContentView = (View) field.get(mSwipeRefreshLayout);
} catch (Exception e) {
e.printStackTrace();
}
});
}
即让此view所有的工作都做完后再发消息,获取其变量,这样做就ok了。