应用被强杀了怎么办

应用在后台运行时很容易被强杀,这很正常,但是回到前台时,很容易出现空指针的情况。怎么解决这样的问题,且看看Stay的见解。

我们先跳出来看看android的app运行原理。

app在后台被强杀,是在内存不足的情况下被强制释放了,也有一些恶心的rom会强制杀掉那些后台进程以释放缓存以提高所谓的用户体验。

我们都觉得android rom很恶心,但同时还是用些更恶心的手法去绕开这些瓶颈。乱,是因为在最上层没有一个很好的约束,这也是开源的弊端。anyway。我们还是得想破脑袋来解决这些问题,否则饭碗就没了。

我们先来重现这个bug:

假设: App A -> B -> C -> D

在D activity中点Home键后台运行,打开ddms,选中该App进程,强杀。

然后从“最近打开的应用”中选中该App,回到的界面是D activity,假设App中没有静态变量,这个时候是不会crash的,点击返回到C,这个时候也只是短暂黑屏后显示C界面。但如果C中有引用静态变量,并想要获取静态变量中的某个值时,就NullPointer了。

以上复现的流程就几个点,我们展开说下:

1. 当应用被强杀,整个App进程都是被杀掉了,所有变量全都被清空了。包括Application实例。更别提那些静态变量了。

2. 虽然变量被清空了,但Android给了一些补救措施。activity栈没有被清空,也就是说A -> B -> C -> D这个栈还保存了,只是ABCD这几个activity实例没有了。所以回到App时,显示的还是D页面

3. 另外当activity被强杀时,系统会调用onSaveInstance去让你保存一些变量,但我个人觉得面对海量的静态变量,这个根本不够用。

4. 返回到C会黑屏,是因为C要重绘,重走onCreate流程,渲染上需要点时间,所以会黑屏。

大概是以上这些点。如果App中没有静态变量的引用,那就不用出现NullPointer这个crash,也就不需要解决。一旦你有静态变量,或者有些Application的全局变量,那就很危险了。比如登录状态,user profile等等。这些值都是空了。

肯定会有人说,这没关系啊,所有的静态变量都改到单例去不就好了吗?然后附加上一些持久化cache,空了再取缓存就ok了嘛。嗯,这肯定也是一个办法,但是这样的束手束脚对开发来说也是痛苦,至少需要多30%的编码时间才能全部cover。另外,还有那么多帮你挖坑的队友,难省心啊。

既然App都被强杀了,干嘛不重新走第一次启动的流程呢,别让App回到D而是启动A,这样所有的变量都是按正常的流程去初始化,也就不会空指针了,对吧?有人说这方案用户体验一点都不好呀。但哪有十全十美的事呢,是重走流程好,还是一点一个NullPointer好?好好去沟通,相信产品也不会为难你的。当然你也可以拿iOS来举例,iOS在最近打开的应用里杀了某个App,重新点击那个App,还是会重走流程的啊。

如果你接受我的这个解决方案,那且想想如何让它不回到D而是重走流程呢?也就是说中断D的初始化而回到A,并且按back键,不会回到D,C,B。考虑一下。

我们先实例化这个场景吧。

A 为App的启动页

B 为登录页

C 为首页

D 为二级页面

简单说下解决方案,剩下的自己思考。

1. 把首页launchMode设置为singleTask,具体为什么我就不说了,自己google。

2. 在BaseActivity中onCreate中判断App是否被强杀,强杀就不往下走,直接重走App流程。

3. 首页起一个承接或者中转的作用,所有跨级跳转都需要通过首页来完成。

再给个提示,以上场景的解决方案也可以用于解决其它相关问题:

1. 在任意页面退出App

2. 在任意页面返回到首页

3. 在任意页面注销或者token失效回到登录页

其实最重要的知识点就是launchMode,很多人面试的时候都能背出来,甚至是原理。但真正会合理应用它们的少之又少。有的时候,技术的优劣体现于此。生搬硬套肯定是站不到最高点的。

题外话:

当我第一次碰到这种问题的时候就在想,为啥Android非得这么来实现,既然都已经把应用强杀了,为什么还把栈信息保存下来了。既然把栈信息保存下来,为什么不把整个App变量都cache到硬盘上呢。这样还能节省ram,每个当前运行的App分到的最大内存也不用再加限制了啊。这样的话Bitmap的OOM也很难发生了。多好。好吧,iOS的内存管理貌似就是这样的机制(我这是白话文,勿较真)

有很多bug都是系统级的限制,虽说没有解决不了的技术,但是偏要钻牛角尖偏要用自以为的方式去解决问题,那么就是坑自己,并且也坑了队友。

做技术越久,越能感受到,难做的不是技术,而是业务。如何理解业务,以及背后的需求本质,是开发中最最重要的事情。与其盲目的拿需求就开始写代码,不如花上些时间去理解需求。弄清前因后果,想好封装与扩展。这些是对思维逻辑的锻炼,并且也是技术提升最快的方式。

原文发布于微信公众号 - 小巫技术博客(wwjblog)

原文发表时间:2016-04-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏腾讯技术工程官方号的专栏

免费开放阅读 | 数据库管理系统的事务原理(上)

作者介绍: 那海蓝蓝,腾讯技术工程事业群计费平台部金融云TDSQL数据库T4级专家,熟悉PostgreSQL、MySQL、Informix等数据库内核技术,著有...

5358
来自专栏晨星先生的自留地

老司机带我飚车(2)一个有趣的漏洞PoC调试

3226
来自专栏小樱的经验随笔

深入理解USB流量数据包的抓取与分析

在一次演练中,我们通过wireshark抓取了一个如下的数据包,我们如何对其进行分析?

3472
来自专栏coding

听说,撸代码,ide与vim更配哦vim折腾记vim常用命令

在选择编辑器上面,我是一个纠结的人,曾经年少的我执着地追求一款万能的编辑器,可以支持所有编辑语言,灵活可定制,可纯粹用键盘操作。符合这种条件的编辑器,非vim莫...

1012
来自专栏视频咖

如何写出一手好的小程序代码,从架构说起

? 作为微信小程序底层 API 维护者之一,经历了风风雨雨、各种各样的吐槽。为了让大家能更好的写一手小程序,特地梳理一篇文章介绍。如果有什么吐槽的地方,欢迎去...

5122
来自专栏Aloys的开发之路

Python第三方常用工具、库、框架等

       Python ImagingLibrary(PIL):它提供强大的图形处理的能力,并提供广泛的图形文件格式支持,该库能进行图形格式的转换、打印和显...

44710
来自专栏向治洪

android开发性能分析

1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾。不想写的原因是随便上网一搜一堆关于性能的建议,感觉大家你一总结、我一总结的都说到了很多优化注意事项...

2545
来自专栏FSociety

Python爬取猫眼「碟中谍」全部评论

评论算保存完了,近期会再做一个关于此次数据的可视化分析。另外阿汤哥真心太帅了,全程打肾上腺素,各位还没去看的赶紧~

790
来自专栏哲学驱动设计

产品前端重构(TypeScript、MVC框架设计)

最近两周完成了对公司某一产品的前端重构,本文记录重构的主要思路及相关的设计内容。 公司期望把某一管理类信息系统从项目代码中抽取、重构为一个可复用的产品。该系统的...

2608
来自专栏塔奇克马敲代码

Windows平台下源码分析工具

2333

扫码关注云+社区

领取腾讯云代金券