一个UI BUG引发的血案

发表于:2018-2-24 10:12

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:hamberluo    来源:掘金

  起因
  最近有同事和用户反馈,说应用首页的 4 个 tab 在使用了一段时间之后 reselect 重复点击选中时没有触发刷新,并且是小概率事件。本地复现无果后,先进行代码排查。
  排查过程
  反馈的这个问题有 2 个信息:
  · 点击 tab 没有反应(说明执行过程遇到错误)
  · 点击 tab 没有崩溃(说明这个错误没有引起闪退)
  看了代码后发现,逻辑上并没有条件判断的 return 逻辑,并且在监听 tab 的事件上使用了 RxJava ,那么结论显而易见了,是 RxJava 吃掉了本该引起崩溃的异常。
  再往下跟,发现事情可能没有这么简单,这个异常是一个空指针异常,表示某个 ui 控件的成员变量没有初始化。
  · ui 控件的成员变量初始化是交给 butterknife 的
  · butterknife 的逻辑是在 Fragment 的 onCreateView 方法中执行
  说明这个 onCreateView 的生命周期方法没有被执行到,那么为什么没有被执行到呢?联想到用户反馈的一个条件是使用了一段时间,那么这个问题很可能和 savedInstanceState 有关。
  一般和 tab 组合使用的 Fragment 会用到 FragmentPagerAdapter ,而我们在对 Fragment 做重用(即利用 savedInstanceState 进行初始化)的时候,不仅仅需要考虑 Fragment 自身的恢复,还要考虑 Fragment 所包含的成员变量的恢复。对于初始化逻辑嵌套好几层的来说,就需要传递好几层的 savedInstanceState ,但代码中明显是漏掉不少的。
  提到 savedInstanceState ,就不得不说开发者模式下的不保留活动了。开启不保留活动后,这个问题就变成必现的了。
  这让我重新思考到底什么时候需要做恢复。
  · 首页的这 4 个 tab 对应的 fragment 是不需要做恢复的
  · 在有用户输入的场景(如果没有备份的草稿逻辑,需要做恢复)
  · 在数据量不大的关键 ui 上需要做恢复
  去掉恢复逻辑后,这个问题解决了,但处理过程中发现了其他的问题。 Fragment 这个东西坑特别多,因为这个东西可以 new 出来,但又有 Activity 类似的生命周期。那么在写代码的时候就要特别注意。
  · 尽量不要增加不必要的 public 方法
  · 所有的非生命周期 public 方法都要进行 isAdded 的判断和 final 关键字防止 Override
  · 特别注意下 setUserVisibleHint 这个方法是不保证在生命周期内的
  到这里就结束了么?我也差点以为结束了,结果又发现一个问题,也是不保留活动引起的(或者说使用了很长一段时间,中间只用 home 键切出)。
  问题描述:打开若干个页面后,按 home 键切回桌面,再进入后,右滑返回动画异常。
  这个问题的原因是切回桌面的时候 MainActivity 被销毁了,再次进入后又重新创建,但其他几个 activity 并没有重新创建(推测是由于 MainActivity 的 singleTask 属性),而右滑返回的动画是依赖于 ActivityStack (手动维护)的,很明显 MainActivity 从 Stack 的栈底被加到栈顶了,造成了动画的异常。
  解决方法也比较简单,新增一个叫做 ActivityStackBottom 的接口让 MainActivity 去实现,然后代码如下:
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if (activity instanceof ActivityStackBottom) {
mActivityStack.add(0, activity);
} else {
mActivityStack.add(activity);
}
}
  这样就确保 MainActivity 永远在栈底了。
  后话
  到这里,目前发现的问题也就解决了,但恐怕其他地方还有不少问题,总结下:
  · Android 自己的规则是很重要的东西,对生命周期函数的理解不仅仅在顺序和交互上。
  · 一个问题可能会牵涉到另一个问题,解决问题的过程很像《唐人街探案》的案中案,不要轻易地认为事情到这里就结束了。
  · 在无法复现的时候多想想代码本身的问题,但也不要过分纠结在代码中,从代码问题追溯到具体场景(比如解决恢复问题并不是完善恢复逻辑,而是先思考需要恢复的场景)。
  好了不说了,要去解决另一个棘手的问题了,今天的重构任务要完不成了,但 Never 哭哭~~

上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号