美文网首页APP开发经验总结
SwipeRefreshLayout无法下拉刷新了

SwipeRefreshLayout无法下拉刷新了

作者: 尹star | 来源:发表于2016-09-16 10:33 被阅读3509次

    某次项目上线前,QA的妹纸忽然发现一个严重的bug,列表无法进行下拉刷新了。使用场景是当前列表数据为空,或者请求失败时,又没有加载到缓存数据的情况,也就是EmptyView页面无法进行下拉刷新了。关于这个问题,我曾重点解决过,所以当妹纸提出这个bug时,作为程序员的职业习惯第一反应是:这不可能,你看我这好着呢。

    然而经过几轮测试发现问题是真实存在的,这么简单的一个SwipeRefreshLayout为什么出了这么多幺蛾子呢。

    android.jpg

    最开始采用SwipeRefreshLayout作为下拉刷新控件,但是产品经理还没来得及定义EmptyView页长什么样就跑路了,所以这个问题就交给程序员自己解决了,那当然最简单的方案就是在Empty页中间放一个按钮,请求失败或者无网络的时候分别提示用户点击重试或者设置网络,这也是大多数APP的选择。本着人人都是产品经理的理念,个人认为即便请求失败或者空数据的情况下,仍然采用下拉刷新的操作来进行retry,在交互上可以保证用户习惯的一致性,而且滑动操作也比点击操作有更好的体验,也是交互和设计的趋势所向。

    当时第一版开发时间特别紧,所以关于这个EmptyView的实现方案特别挫。直接在xml里包了两个SwipeRefreshLayout,一个用来下拉刷新列表,一个用来下拉刷新EmptyView,然后在代码里控制二者的显示与隐藏。方案虽然很挫,但也没出什么大问题,就这么作为临时方案先用着。

    第二版的时候把这个方案替换掉了,去掉了EmptyView外面包裹的SwipeRefreshLayout。

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
     >
    <android.support.v4.widget.SwipeRefreshLayout 
           android:id="@+id/swipeLayout"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:orientation="vertical">
            <android.support.v7.widget.RecyclerView
              android:id="@+id/list_view"
              android:layout_width="match_parent"
              android:layout_height="match_parent"/>
    </android.support.v4.widget.SwipeRefreshLayout>
       <TextView
            android:id="@+id/error_view"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:gravity="center"
            android:textColor="@color/subhead_text_color"
            android:textSize="@dimen/primary_tip_size"
            android:visibility="gone" />
    </RelativeLayout>
    

    直接这样,EmptyView依然可以下拉刷新,这里依赖的原理是点击事件的穿透,即便当前显示在上层的视图是EmptyView,如果不给EmptyView添加任何事件,那么事件会向下传递,传递给下面的SwipeRefreshLayout,有时候这种奇技淫巧还是挺有用的。

    然后这个方案就一直延续着,直到开头提到的QA妹纸发现无法下拉刷新的bug为止,都没有发现什么问题。那这个bug到底是什么原因引起的呢?我第一反应是,有人动我代码了,于是我compare了当前节点与上次发版的节点,代码一毛一样,没有人动我代码,但是线上的就OK啊。刚开始我跟QA妹纸打包票,半个小时解决问题,而实际上最后和同事们花了近半天时间才解决。

    问题走进了死胡同,首先是看了半个小时代码,无法准确定位问题。compare了两个节点的代码,依然无法定位,那还是只能采用笨办法了,排除法。上次发版距本次发版,这中间已经产生了几十个commit,到底是哪次commit后出现了这个问题,这是第一个要定位的问题,于是乎一一checkout验证,当然这也是有技巧的,虽然没验证过到底怎样的查找方式会比较快,习惯性的在这几十个commit中来了个二分查找。每次checkout编译运行测试也是很耗时的,而且这个工作很枯燥,只能发动大家一块来找茬啦。

    找了好大一会,终于定位到了一个commit,这个commit 之前OK,而之后就悲剧了。那毫无疑问就是它搞得鬼,但这个commit毫不起眼,根本没有什么伤筋动骨的修改。那如果代码上没有大修改,就要注意下AndroidManifeset和gradle了。gradle中增加了些看似无关紧要的引用,肉眼也实在看不出有什么问题,但如果把这些新增的引用包去掉,问题马上就解决了。但新增的这些包与SwipeRefreshLayout可是八竿子打不着啊,但SwipeRefreshLayout是android.support.v4包里的控件,会不会是support.v4包更换了新的版本?

    展开External Libraries 发现果然有两个support.v4包。


    Paste_Image.png

    难道是这两个包里的SwipeRefreshLayout实现不太一样,或者有做改动?

    Paste_Image.png

    找到源码一探究竟,拉出support.v4-23.0.1和support.v4-23.3.0里的SwipeRefreshLayout源码,一看行数都不一样,前者1152行,后者1163行。我勒个去还真是做了修改,难道是升级的时候没有向下兼容吗?compare了下两个版本的代码,发现事件分发那里确实做了些修改。

    Paste_Image.png

    猜想大概是这个原因,利用Click-Through来实现下来刷新不能奏效了。但是我仍然想用以前的方案,怎么办呢?
    有两个办法,一个是指定使用老版本的support.v4包。二是把老版本的代码copy出来放到自己工程里。最后我们采用了比较优雅一点的方式,在gradle里强制指定了版本。

    configurations.all {
        resolutionStrategy {
            force 'com.android.support:support-v4:23.0.1'
        }
    }
    

    最后一个问题,为什么会有两个support-v4包呢?刚开始的时候用recyclerview,SwipeRefreshLayout这些空间的时候导入了一个support-v4包,这个版本相对较低,是support-v4:23.0.1,后来一直没有更新。随着项目的进行,另外的同学在导入其他第三方包的时候,这个第三方包依赖了一个比较新的support-v4包,support.v4-23.3.0。所以这个时候SwipeRefreshLayout默认使用了比较新的额代码,就导致了开头所提到的那个bug。友情提示:更新引用包是有很大风险的,一定要多测试。有时间再说下另外一次更新包挖的坑。

    相关文章

      网友评论

      • Kuma_233:我想问个问题:android:id="@+id/error_view" 如果显示后。因为将屏幕挡住后,不改变布局的情况下,swipeLayout下拉刷新后一闪怎么解决。
        b578703a6efb:你解决了吗这个问题? 我今天也遇到了
      • kisass:楼主如何不给EmptyView添加任何事件,求指教
        尹star: @kisass 断点看看
        kisass:@尹star 不行啊,没反应,下拉不了
        尹star: @kisass 什么都不写就是了,不加点击
      • 满月写:configurations.all {
        resolutionStrategy {
        force 'com.android.support:support-v4:23.0.1'
        }
        }

        这个写在哪个文件啊
      • hackware:重写canScrollVertical试试

      本文标题:SwipeRefreshLayout无法下拉刷新了

      本文链接:https://www.haomeiwen.com/subject/ootusttx.html