CommonPullToRefresh:SwipeRefreshLayout嵌套RecyclerView,配合SwipeRefreshHelper 加载更多报错 解决方案

CommonPullToRefresh是一个开源的支持上拉刷新下拉加载更多的控件的库

附上原作者介绍:

android-Ultra-Pull-To-Refresh的基础上增加了加载更多的支持,感谢作者

  • 下拉刷新支持大部分viewListViewScrollViewWebView等,甚至一个单独的TextView
  • 加载更多目前支持ListViewRecyclerViewGridViewSwipeRefreshLayout
  • 支持自定义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了。



猜你喜欢

转载自blog.csdn.net/qq_20089667/article/details/80607385