Android-App-启动优化全记录

  • Application 和主 Activity 的 onCreate 中异步初始化某些代码

启动过程中繁忙的 cpu

启动过程中繁忙的 SystemServer

GC 优化

启动过程中减少 GC 的次数

  • 避免进行大量的字符串操作,特别是序列化和反序列化
  • 频繁创建的对象需要考虑复用
  • 转移到 Native 实现

可以参考下面这篇文章 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」)

IO 优化

启动过程中负载比较高,有许多系统 IO 都在此时发生,这时候 IO 的性能下降会比较快,此时 App 中的 IO 操作会比平时更慢一些,尤其是在性能比较差的机器上。

IO 分网络 IO 和磁盘 IO ,启动过程中不建议进行网络 IO ,对于磁盘 IO 则要细扣,邵文在高手课里面有讲到:

  1. 我们要清楚启动过程中读了什么文件、多少个字节、 Buffer 是多大,使用了多长时间、在什么线程等一系列信息
  2. 进行启动过程中的 IO 监控,微信在监控 IO 时发现有用户的 db 文件达到了 500MB

image

下面图中可以看到低内存的时候,启动应用主线程有较多的 IO 等待(UI Thread 这一栏,橘红色代表 IO 等待 )

资源重排

利用 Linux 的 IO 读取策略,PageCache 和 ReadAhead 机制,按照读取顺序重新排列,减少磁盘 IO 次数 。具体操作可以参考支付宝 App 构建优化解析:通过安装包重排布优化 Android 端启动性能 这篇文章

Linux 底层文件系统中 VFS 上次 App 进程之间,存在一层 pagecache,pagecache 由内存中的物理 page 组成,其内容对应磁盘上的 block。Pagecache 的大小是动态变化的,可以扩大,也可以在内存不足时缩小。Cache 缓存的存储设备被称为后备存储(backing store),一个 page 通常包含多个 block,这些 block 不一定是连续的

利用文件重布局结合Pagecache 机制可以减少启动过程中的真正 IO 的次数,简单的说,通过文件重布局的目的,就是将启动阶段需要用到的文件在 APK 文件中排布在一起,尽可能的利用 pagecache 机制,用最少的磁盘 IO 次数,读取尽可能多的启动阶段需要的文件,减少 IO 开销,从而达到提升启动性能的目的

类重排

类重排的实现通过 ReDex 的 Interdex 调整类在 Dex 中的排列顺序。Interdex 优化不需要去分析类引用,它只需要调整 Dex 中类的顺序,把启动时需要加载的类按顺序放到主 dex 里,这个工作我们完全可以在编译过程中实现,而且这个优化可以提升启动速度,优化效果从 facebook 公布的数据来看也比较可观,性价比高。具体实现可以参考 Redex 初探与 Interdex:Andorid 冷启动优化

主页面布局优化

应用主界面布局优化是老生常谈了,综合起来无非就是下面两点,这个需要结合具体的界面布局去做优化,网上也有比较多的资料可以查阅

  • 通过减少冗余或者嵌套布局来降低视图层次结构
  • 用 ViewStub 替代在启动过程中不需要显示的 UI 控件
  • 使用自定义 View 替代复杂的 View 叠加

闲时调用

IdleHandler:当 Handler 空闲的时候才会被调用,如果返回 true, 则会一直执行,如果返回 false,执行完一次后就会被移除消息队列。比如,我们可以将从服务器获取推送 Token 的任务放在延迟 IdleHandler 中执行,或者把一些不重要的 View 的加载放到 IdleHandler 中执行

类加载优化

可以在 systrace 生成的文件中看到 verifyClass 过程,因为需要校验方法的每一个指令,所以是一个比较耗时的操作。

App 瘦身

App 瘦身包括代码瘦身和资源瘦身,通常的做法如下:

  • Inspect Code :Android Studio 提供的代码审查工具,实际上是内嵌了 Lint
  • 代码混淆
  • 图片格式的选择:如果对图片的要求不高,可以换成 565
  • 接入资源混淆
  • 减少 Dex 数量

选择合适的启动框架

启动优化整个流程的梳理,流程的梳理,我们这里引入了一个有向无环图的概念,我们会把整个的概念梳理成有向无环图的结构,然后会去挨个加载。右边的部分,可以看到我们其实在启动的时候,首先会去加载一些必要的启动项,必要的启动项是左边流程,会用一个多进程的方式加载,以来有向无环图进行控制,比如说我是在非必须的时候启动加载我可以放在后面再去加载。当然在整个有向无环图的顺序加载,其实还是会做一些进程的判断,要判断某些项目是不是要在主进程里加载,某些要在初始进程里面加载

从 Spark 的 DAGScheduler 中领悟到它的核心思想,面向阶段调度(Stage-Oriented Scheduler):把应用划分成一个个的阶段(Stage),再把任务(Task)安排到各个阶段中去,任务的编排则是通过构建 有向无环图(DAG),把任务依赖通过图的方式梳理得 井井有条。因为它分阶段执行,先集中资源把阶段一搞定,再齐心协力去执行阶段二,这样即能控制拥塞,又能保证时序,还能并发执行,让设备性能尽可能得到发挥

大家可以参考淘宝的全链路优化的案例:历时1年,上百万行代码!首次揭秘手淘全链路性能优化(上)

启动网络链路优化

问题和优化点

  • 发送处理阶段:网络库bindService影响前x个请求,图片并发限制图片库线程排队
  • 网络耗时:部分请求响应size大,包括 SO文件,Cache资源,图片原图大尺寸等
  • 返回处理:个别数据网关请求json串复杂解析严重耗时(3s),且历史线程排队设计不合适
  • 上屏阻塞:回调UI线程被阻,反映主线程卡顿严重。高端机达1s,低端机恶化达3s以上
  • 回调阻塞:部分业务回调执行耗时,阻塞主线程或回调线程

优化

  • 多次重复的请求,业务方务必收敛请求次数,减少非必须请求。
  • 数据大的请求如资源文件、so文件,非启动必须统一延后或取消。
  • 业务方回调执行阻塞主线程耗时过长整改。我们知道,肉眼可见流畅运行,需要运行60帧/秒, 意味着每帧的处理时间不超过16ms。针对主线程执行回调超过16ms的业务方,推动主线程执行优化。
  • 协议json串过于复杂导致解析耗时严重,网络并发线程数有限,解析耗时过长意味着请求长时间占用MTOP线程影响其他关键请求执行。推动业务方handler注入使用自己的线程解析或简化json串。

预加载

Activity 打开之前就预加载数据,在 Activity 的 UI 布局初始化完成后显示预加载的数据,大大缩短启动时间。 可以参考 :https://github.com/luckybilly/PreLoader/blob/master/README-zh-CN.md

保活

保活,是各个应用开发者的噩梦,也是 Android 厂商关注和打击的重点。不过从启动的角度来看,如果应用进程不被杀,那么启动自然就快了,所以保活对应用启动速度也是有极大的帮助。

当然这里说的保活,并不是建议大家用各种黑科技、相互唤醒、通知轰炸这种保活手段,而是提供真正的功能,能让用户觉得你在后台是合理的、可以接收的。比如在后台的时候,资源能释放的都释放掉,不要一直在后台做耗电操作,该停的服务停掉,该关的动画关掉。

当然对于应用开发者来说,上面说的都太多理想化了,而且目前的手机厂商也会很暴力,应用到了后台就会处理掉,不过这毕竟是一个方向,Google 也在规范应用后台行为和规范厂商处理应用这两方面都在做努力,Android 系统的生态,还是需要应用开发者和 Android 厂商一起取改善。

当然保活还有一条路就是走跟厂商的合作,优化后台内存、去掉重复拉起、去掉流氓逻辑、积极响应低内存警告,做好这些话后可以跟系统厂商联系,谈放到查杀白名单和自启动白名单的可行性

业务梳理

这里涉及到具体的业务,每个 App 都不一样,但是所要做的事情都是一样的,下面是邵文在高手课里面提到的:

  • 梳理清楚启动过程中的每一个模块,哪些是一定需要的,那些是可以砍掉,那些是可以懒加载的
  • 根据不同的业务场景决定不同的启动模式
  • 懒加载防止集中化

可以把具体的业务分为下面四个维度(此处图文来自https://juejin.im/post/5c21ea325188254eaa5c45b1#heading-5

  • 必要且耗时:启动初始化,考虑用线程来初始化
  • 必要不耗时:首页绘制
  • 非必要但耗时:数据上报、插件初始化
  • 非必要不耗时:不用想,这块直接去掉,在需要用的时再加载

然后按需进行加载优化

业务优化

  1. 优化业务中的代码效率,抓大放小,先从比较明显的瓶颈处下手,逐步进行优化
  2. 历史债务要偿还,历史的代码要重构,不能一直拖着

具体的业务会有具体的优化场景,大家可以参考这篇文章中的优化流程和优化项(https://www.jianshu.com/p/f5514b1a826c):

1. 数据库及IO操作都移到工作线程,并且设置线程优先级为THREAD_PRIORITY_BACKGROUND,这样工作线程最多能获取到10%的时间片,优先保证主线程执行
2. 流程梳理,延后执行;实际上,这一步对项目启动加速最有效果。通过流程梳理发现部分流程调用时机偏早、失误等,例如:
** 1. 更新等操作无需在首屏尚未展示就调用,造成资源竞争**
** 2. 调用了IOS为了规避审核而做的开关,造成网络请求密集**
** 3. 自有统计在Application的调用里创建数量固定为5的线程池,造成资源竞争**
** 4. traceview功能说明图中最后一行可以看到编号12执行5次,耗时排名前列;此处线程池的创建是必要但可以延后的**
** 5. 修改广告闪屏逻辑为下次生效**
3. 去掉无用但被执行的老代码
4. 去掉开发阶段使用但线上被执行的代码
5. 去掉重复逻辑执行代码
6. 去掉调用三方SDK里或者Demo里的多余代码
7. 信息缓存,常用信息只在第一次获取,之后从缓存中取
8. 项目是多进程架构,只在主进程执行Application的onCreate()

减少Activity的跳转层次

StartingWindow 会在用户点击 App 后立即创建并显示,在 AppWindow 创建好之后,StartingWindow 消失,AppWindow 显示

默认 App 的启动窗口流程

StartingWindow(SystemWindow)
->MainActivity(AppWindow)

大部分三方 App 启动流程

StartingWindow(SystemWindow)
-> SplashActivity(AppWindow)
-> MainActivity(AppWindow)

糟糕一点的启动流程是这样的

StartingWindow(SystemWindow)
-> MainActivity(AppWindow)
-> SplashActivity(AppWindow)
-> MainActivity(AppWindow)

更糟糕一点的启动流程:去掉了 StartingWindow

SplashActivity(AppWindow)
-> MainActivity(AppWindow)

其实对用户来说,第一种启动流程是最好的,只涉及到一次窗口的切换;但是部分 App 由于广告页的需求,会使用第二种流程 ;但是尽量不要使用第三种和第四种启动流程,体验非常不好

厂商优化

除了 App 自身的优化之外,Android 框架对应用启动也是非常关注的,做了比较多的优化,下面简单说一下思路,各个厂商的实现也不太一样,但是基本上都会有,有些是硬核代码优化,有的是利用系统策略做优化。

厂商的策略各不相同,这里只是简单的提一下思路。

启动加速

App 启动的时候,系统会对要启动的应用做绝对的资源倾斜,比如 CPU、IO、GPU 等,这一点大家抓个 Systrace 看一下即可,不管是频率还是调度算法,正在启动的 App 绝对是当时的系统 VIP 客户

image

部分厂商也提供了资源调度的 SDK ,应用可以接入这些 SDK,在需要资源的时候直接调用 SDK 获取

PreFork

Android Q 加入了 PreFork 机制,会先 fork 几个空进程,当 App 启动的时候,可以直接复用这几个空进程,而不用重新去 fork

2,348K: usap32 (pid 18731)
2,346K: usap32 (pid 18702)
2,343K: usap32 (pid 18707)
2,342K: usap32 (pid 18729)
2,341K: usap32 (pid 18711)
2,335K: usap32 (pid 20322)
2,335K: usap32 (pid 20325)
2,333K: usap32 (pid 20319)
2,333K: usap32 (pid 20320)
2,333K: usap32 (pid 20321)

1,509K: usap64 (pid 21169)
1,509K: usap64 (pid 21180)
1,507K: usap64 (pid 21171)
1,452K: usap64 (pid 21513)
1,450K: usap64 (pid 21506)
1,449K: usap64 (pid 21512)
1,447K: usap64 (pid 21511)
1,445K: usap64 (pid 21514)

启动消息重排

启动的时候,对启动过程中的 Message 进行重新排列

主线程、渲染线程加速

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

中…(img-TWWv0m8L-1714962235520)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android新闻App的新闻推荐算法是一个复杂的系统,旨在根据用户的兴趣和偏好,为其提供个性化的新闻推荐内容。下面将就该算法进行简要介绍。 首先,新闻推荐算法会根据用户在App上的行为和兴趣,建立用户画像,包括用户的阅读历史、喜好领域、点击行为等等。这些数据将被用作推荐系统中的输入。 接着,算法会根据用户画像和当前的热点话题等因素,从新闻数据库中选取一些候选新闻。这些候选新闻会通过一系列的预处理步骤,如文本分词、关键词提取、情感分析等等,将新闻内容转化为更易于计算和比较的特征。 然后,推荐系统会根据用户画像和候选新闻的特征,计算它们之间的相似度或匹配程度。这可以使用一些机器学习算法,如协同过滤、内容过滤等来实现。 最后,通过相似度或匹配程度的排名,推荐系统会选择最相关的几篇新闻,将其推送给用户。 值得注意的是,推荐算法还会考虑一些其他的因素,例如新闻的发布时间、新闻的信源可靠性等等,以提供更好的用户体验和服务质量。 总体而言,Android新闻App的新闻推荐算法是一个复杂的系统,涉及数据收集、特征提取、相似度计算等多个环节。通过不断优化算法和引入新的技术,可以提供更符合用户兴趣和需求的个性化推荐内容。 ### 回答2: Android新闻app的新闻推荐算法基于用户的兴趣和行为进行个性化推荐。该算法主要包括以下几个方面: 1. 用户兴趣模型:系统通过分析用户的历史浏览记录、收藏、点赞等行为数据,构建用户的兴趣模型。这个模型可以通过机器学习算法不断优化,更准确地反映用户的兴趣爱好。 2. 内容相似度计算:系统通过对新闻文章的文本内容进行自然语言处理,提取关键词、标签等信息,计算不同文章之间的相似度。对于用户喜欢的文章,系统可以根据相似度来推荐类似的新闻。 3. 协同过滤:该算法通过分析不同用户的行为数据,发现用户之间的相似性和差异性。当一个用户浏览或点赞了某篇文章时,系统会查找具有类似兴趣的其他用户,并将这些用户也推荐该文章。 4. 实时热点推送:系统会根据实时的热点新闻、热门话题等进行推送。这些推送内容通常是根据大众的兴趣和关注度来确定的,以满足用户获取最新、最热门新闻的需求。 5. 推荐算法优化:系统会根据用户的反馈和行为数据不断调整和优化推荐算法。例如,用户可以给推荐的新闻进行点赞、收藏或举报,这些反馈数据可以用于优化推荐算法的准确性和个性化程度。 综上所述,Android新闻app的新闻推荐算法通过分析用户的兴趣和行为数据,结合内容相似度计算和协同过滤等方法,实现个性化的新闻推荐。同时,通过实时热点推送和算法优化,满足用户获取最新和感兴趣的新闻的需求。 ### 回答3: Android新闻App新闻推荐算法是通过分析用户的兴趣和行为数据,为其个性化地推荐相关的新闻内容。该算法主要包括以下几个方面的内容: 1. 用户兴趣建模:通过收集和分析用户的行为数据,如点击历史、收藏、分享等,来了解用户的兴趣领域和偏好。通过使用机器学习算法,可以对用户的兴趣进行建模,如通过聚类算法将用户分为不同的兴趣群体。 2. 内容特征提取:对新闻内容进行特征提取,包括关键词、主题、情感等。通过文本挖掘算法对新闻进行自动标签和分类,从而将新闻与用户的兴趣进行匹配。 3. 协同过滤算法:通过分析用户行为数据,发现用户的行为模式和偏好,并将相似用户推荐给他们,从而实现用户之间的信息协同。这种方法可以增加用户对新闻内容的关注度,并提高推荐算法的准确性。 4. 排序算法:根据用户的兴趣和需求,对新闻进行个性化排序,将最相关和有吸引力的新闻展示在用户的推荐列表中。排序算法可以基于用户的历史行为和兴趣模型,使用协同过滤、基于内容的推荐等方法进行实现。 5. 多样性和新颖性考虑:在进行新闻推荐时,还需要考虑到多样性和新颖性的因素。不能仅仅满足用户的已知偏好,还需要引入一定的随机性和冷启动策略,给用户带来新鲜和意外的新闻内容。 以上是Android新闻App新闻推荐算法的一般流程和关键点。通过对用户行为数据的分析和个性化匹配,可以提高用户的满意度和参与度,提升App的用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值