SwipeRefreshLayout无法下拉刷新了

2024-05-28 12:18

本文主要是介绍SwipeRefreshLayout无法下拉刷新了,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 问题

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

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

2.问题背景

最开始采用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到底是什么原因引起的呢?

3. 思路(我觉得蛮重要的)

我第一反应是,有人动我代码了,于是我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包

这里写图片描述

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

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

这里写图片描述

4. 解决办法

猜想大概是这个原因,利用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。友情提示:更新引用包是有很大风险的,一定要多测试。有时间再说下另外一次更新包挖的坑

这篇关于SwipeRefreshLayout无法下拉刷新了的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1010545

相关文章

Idea实现接口的方法上无法添加@Override注解的解决方案

《Idea实现接口的方法上无法添加@Override注解的解决方案》文章介绍了在IDEA中实现接口方法时无法添加@Override注解的问题及其解决方法,主要步骤包括更改项目结构中的Languagel... 目录Idea实现接China编程口的方法上无法添加@javascriptOverride注解错误原因解决方

golang1.23版本之前 Timer Reset方法无法正确使用

《golang1.23版本之前TimerReset方法无法正确使用》在Go1.23之前,使用`time.Reset`函数时需要先调用`Stop`并明确从timer的channel中抽取出东西,以避... 目录golang1.23 之前 Reset ​到底有什么问题golang1.23 之前到底应该如何正确的

解决Cron定时任务中Pytest脚本无法发送邮件的问题

《解决Cron定时任务中Pytest脚本无法发送邮件的问题》文章探讨解决在Cron定时任务中运行Pytest脚本时邮件发送失败的问题,先优化环境变量,再检查Pytest邮件配置,接着配置文件确保SMT... 目录引言1. 环境变量优化:确保Cron任务可以正确执行解决方案:1.1. 创建一个脚本1.2. 修

element-ui下拉输入框+resetFields无法回显的问题解决

《element-ui下拉输入框+resetFields无法回显的问题解决》本文主要介绍了在使用ElementUI的下拉输入框时,点击重置按钮后输入框无法回显数据的问题,具有一定的参考价值,感兴趣的... 目录描述原因问题重现解决方案方法一方法二总结描述第一次进入页面,不做任何操作,点击重置按钮,再进行下

Java子线程无法获取Attributes的解决方法(最新推荐)

《Java子线程无法获取Attributes的解决方法(最新推荐)》在Java多线程编程中,子线程无法直接获取主线程设置的Attributes是一个常见问题,本文探讨了这一问题的原因,并提供了两种解决... 目录一、问题原因二、解决方案1. 直接传递数据2. 使用ThreadLocal(适用于线程独立数据)

使用@Slf4j注解,log.info()无法使用问题

《使用@Slf4j注解,log.info()无法使用问题》在使用Lombok的@Slf4j注解打印日志时遇到问题,通过降低Lombok版本(从1.18.x降至1.16.10)解决了问题... 目录@Slf4androidj注解,log.info()无法使用问题最后解决总结@Slf4j注解,log.info(

三国地理揭秘:为何北伐之路如此艰难,为何诸葛亮无法攻克陇右小城?

俗话说:天时不如地利,不是随便说说,诸葛亮六出祁山,连关中陇右的几座小城都攻不下来,行军山高路险,无法携带和建造攻城器械,是最难的,所以在汉中,无论从哪一方进攻,防守方都是一夫当关,万夫莫开;再加上千里运粮,根本不需要打,司马懿只需要坚守城池拼消耗就能不战而屈人之兵。 另一边,洛阳的虎牢关,一旦突破,洛阳就无险可守,这样的进军路线,才是顺势而为的用兵之道。 读历史的时候我们常常看到某一方势

ORACLE 11g 创建数据库时 Enterprise Manager配置失败的解决办法 无法打开OEM的解决办法

在win7 64位系统下安装oracle11g,在使用Database configuration Assistant创建数据库时,在创建到85%的时候报错,错误如下: 解决办法: 在listener.ora中增加对BlueAeri-PC或ip地址的侦听,具体步骤如下: 1.启动Net Manager,在“监听程序”--Listener下添加一个地址,主机名写计

使用Qt编程QtNetwork无法使用

使用 VS 构建 Qt 项目时 QtNetwork 无法使用的问题 - 摘叶飞镖 - 博客园 (cnblogs.com) 另外,强烈建议在使用QNetworkAccessManager之前看看这篇文章: Qt 之 QNetworkAccessManager踏坑记录-CSDN博客 C++ Qt开发:QNetworkAccessManager网络接口组件 阅读目录 1.1 通用API函数

Clion不识别C代码或者无法跳转C语言项目怎么办?

如果是中文会显示: 此时只需要右击项目,或者你的源代码目录,将这个项目或者源码目录标记为项目源和头文件即可。 英文如下: