App异常汇总与对策

发布于:2024-05-02 ⋅ 阅读:(28) ⋅ 点赞:(0)

UI交互异常

  1. 空显示/白屏
    1. 一般是因为数据为空或获取失败。要请产品定义加载中、加载失败、数据为空的UI。
  2. 显示不完整、错位
    1. 开发时考虑不同屏幕大小、窗体大小、内容量的兼容,做好对齐和层级的设置。内容量会引起折行、显示不全等问题。
    2. 如果有改变字体大小或多语言设置的需求,应在自测时确保最大字号和最长文字时显示正常。
  3. 格式显示错误。日期、时间、时区、数值、单位、语言等,请产品明确并准确实现。
  4. App启动或进入某界面的时间过长
    1. 耗时操作异步化,让用户更早看到程序界面
    2. 如果必须等某些操作后才好展示,让产品增加loading状态的UI
  5. 连续多次操作,数据异常。一般发生在异步操作的场景
    1. 连续点击按钮。请产品定义loading状态UI,重复点击不响应,或响应前点其它地方都是取消。
    2. 一个长时间的动画过程中执行反向操作,例如游戏开车前进时突然油门不松开地切成倒挡。需要程序做好兼容,请产品确认能不能这样操作,有什么后果。
  6. 异步结果返回时,用户已取消操作。一个极端情况是,服务器已处理了请求但网络正好断了,客户端没收到确认信息。
    1. 通常操作是不管的,下次进入或刷新就能看到最新状态。产品需要知道。
  7. 多个提示(Toast或自消失弹窗)没有依次显示。请产品定义:
    1. 如果提示都要在同一个地方显示,则做好全局管理,用队列做消息缓存,等前一个消息提示正常消失后,从队列取下一个来显示。不能让前一个立刻消失或被遮盖。
    2. 可以做排列显示,即下一个提示在前一个提示的下方,前一个提示消失时,下面的提示自动向上移动
  8. 卡顿
    1. 在UI操作的地方打印日志,分析出耗时操作。要么处理消息过多,要么处理某消息时间过长
    2. 调高UI相关线程的优先级,调低后台线程的优先级
    3. 用性能监控工具实时记录,分析出CPU或内存剧烈波动的操作
    4. 去掉主线程执行的IO操作
    5. 逐步剥离逻辑,定位出产生卡顿的部分。
  9. 换皮肤、配色方案
    1. 漏订阅消息
    2. 漏处理
  10. 图片、音视频不显示或不清晰
    1. 源文件的内容本身有问题
    2. 解码库的参数设置不对
    3. 缓存过小或被清理
    4. 系统不支持源格式的编解码
    5. 系统性能不足,跳帧,降低分辨率、帧率等
  11. 动画不播放
    1. 逻辑状态不对,或执行着多个操作
    2. 相关的View状态不对
  12. 用户体验问题,需求评审的时候就要提出了。别都推责给产品,东西是我们程序员做出来的,可以反向提要求。给三篇参考文章
    1. 需求评审的关注点
    2. 如何写出受技术欢迎的需求文档
    3. 程序员眼中最牛的UI设计师是怎样的?

网络异常

  1. 连接超时、读取超时、发送超时、对方断连/死连
    1. 设好网络库参数(成熟的网络库都有),长连接主动断开重连,短连接主动取消
    2. 和产品确认重试间隔时长,最大重试次数等
    3. 请产品定好相关UI提示
  2. 背压(后向压力,backpresure),数据消费者的处理速度低于数据生产者的生产速度。会造成UI呈现旧数据、数据队列拥塞最终内存耗尽
    1. 数据消费者
      1. 增大缓存,先缓存后处理
      2. 多线程处理
      3. 丢弃或合并处理部分数据
    2. 数据生产者
      1. 增加缓存,合并数据流,由【高频发少数据】变成【低频发多数据】
      2. 降低数据生产频率
      3. 丢弃部分数据。生产后,判断上次发送时间,未达指定时间间隔则丢弃
      4. 增大发送超时时间
  3. 网速波动:其它应用或模块在占用带宽,导致本功能超时
    1. 限速
    2. 主动停止不重要不紧急的网络任务,或降低优先级
    3. 不能对网速有预期,例如觉得1KB数据肯定秒级传完。都要考虑异常
  4. 信号弱,延时高,丢包
    1. 使用tcpdump+wireshark确认问题
    2. 选择更优的链路
  5. 后端
    1. 无响应,按超时处理
    2. 如约地返回错误,请产品定好UI提示
    3. 未定义地返回错误,例如响应体的JSON反序列化失败。catch exception,不能崩溃,日志做好记录,请产品定好提示,一般是直接toast出exception.message,必然的话做重试。

系统或硬件错误

  1. 资源被占用,初始化失败。例如文件、摄像头、端口、设备等已被别的线程、进程、应用打开。
    1. 可能被别的应用占用的资源,要做好打开失败的容错,有一定的UI提示,不能崩溃。
    2. 应用内的多线程/进程处理,应确保只有一个IO线程/进程,同一个资源的读写都在这个IO线程/进程内处理,其余线程/进程通过发消息来执行操作和传递数据。
  2. 无权限或动态申请权限失败。请产品设计做好用户不授权情况下的交互,不能崩溃。
  3. 串口
    1. 数据可能丢失或错乱,应用层协议要做好检验,例如CRC、MD5
    2. 发送或接收的单条电线可能断开,会产生“可接收但发送失败”的情况,得仔细检查
  4. 摄像头打开时间过长
    1. 硬件或系统层优化
    2. 预加载
    3. 请产品定义,用动画优化体感
  5. 摄像头打开异常
    1. 硬件或系统层
    2. 请产品定义,重试规则和用户交互提醒;
  6. 硬件松动。对应的程序异常时,检查硬件状态。
    1. 应用层断连,可以是网卡松了,网线被拔了,使用ifconfig查看网卡状态
    2. 黑屏,检查显卡或监视器连接状态,也可能屏幕电源没接上
  7. 工程样件硬件就是不可靠的
    1. 可以起一个线程,定时检测硬件状态,输入到日志,方便定位问题。
    2. 工程样件的芯片、CPU、GPU固件都可能有bug,可以怀疑到这一层。

SDK错误

  1. 版本不同
    1. 使用SDK都要经过真机自测
    2. 使用更新或更旧的SDK,尝试是否会出现问题
  2. 是否按预期工作,在不同场景下是否行为一致
  3. 处理流程或传参等错误,是否按文档做了
  4. 兼容性,用了当前系统不支持的API
  5. 三方库本身有bug,多加日志来确认。

程序错误

  1. 多个条件同时成立,导致UI或逻辑错误。复杂场景需要列一个表尽可能穷举所有情况,缺漏的请产品补充定义
  2. 死锁、死循环,直接导致ANR
  3. 在子线程调用了需要在主线程调用的方法
  4. C++野指针。用好STD或boost的便捷类
  5. 没有监听/订阅相关消息,状态改变不知道
    1. 确定监听/订阅是否存在重复
    2. 确定程序窗口销毁后停止相应的监听/订阅
  6. 参数未做配置,需要请产品确定默认值
  7. 内存(RAM)用尽,产生OOM
    1. 对大量级的数据进行流式读写,保持较少的数据量在内存中,更多部分仍在磁盘
    2. 检查内存泄漏,主要是排查需要手动release的对象,认真看说明文档
    3. 内存缓存需要限量,超过限额存入磁盘
    4. 用测试工具对复杂场景测一遍,长时间运行
    5. 大型对象慎用单例,不应该使用全局或静态变量保存
    6. 复用频繁创建销毁的对象
    7. 资源和对象及时释放
    8. 循环体内及时释放临时对象,极限情况可主动触发GC
  8. 磁盘(ROM)用尽
    1. 设计时考虑可能占用磁盘空间的数量,做好限额
    2. 产品设计上提供手动清理缓存的入口和缓存占用量的显示
    3. 数据缓存(例如媒体文件或日志)应做好滚动周期的限制,例如每次启动删除一个月前的数据
  9. CPU长时间占用过高
    1. 使用工具找出占用CPU的函数
    2. 使用工具查看UI渲染频率
  10. 切换到后台被杀掉或停止工作,回到前台需要恢复现场
  11. 认证信息过期而未检验,过期后未清理状态
  12. 外部存储器的文件丢失
  13. 外部存储器的文件被错误修改。解析的时候catch异常,无法恢复就删除或赋默认值
  14. 时序
    1. 是否按照预期的顺序执行
    2. 是否按预期的时机初始化完毕
  15. 数值错误
    1. 多线程/进程/应用,异步时序不对
    2. 没有加锁
    3. 共享空间写入乱序,包括内存和磁盘
    4. 异常退出,文件损坏。
  16. 线程过多。其中集中管理线程池。
  17. 背压,参考网络错误中的描述,同理。
  18. 反射操作错误

PS:不可能的异常

我们不是要处理所有的可能性,否则岂不是所有代码都要加try catch?

应该做的是在写代码前就确定可能有什么异常,有约定、协议、规范不会出错的,都不用做防御,在开发阶段最好就是通过崩溃来达成最高级别的警示。还可以加一些assert,在开发阶段澄清所有的异常。assert也可以防止别人错误地使用你的代码。


网站公告

今日签到

点亮在社区的每一天
去签到