Android开发面试【金三】——启动优化

news2024/11/17 12:53:08

前言

一下子来到了,面试的高潮季。金三银四的三月份;在我们Android开发的众多面试中,扑面而来的超多面试题难道很多程序员。

Android的性能优化,主要是从以下几个方面进行优化的: 稳定(内存溢出、崩溃) 流畅(卡顿) 耗损(耗电、流量) 安装包(APK瘦身) 影响稳定性的原因很多,比如内存使用不合理、代码异常场景考虑不周全、代码逻辑不合理等,都会对应用的稳定性造成影响。

本篇我们就来解析,面试题常见面试——Android性能优化之启动优化。

启动优化,常问面试的问题?

1、你做启动优化是怎么做的

2、是怎么异步的,异步遇到问题没有

3、你做了启动优化,觉得有哪些容易忽略的

4、版本迭代导致的启动变慢有好的解决吗

等等一系列演绎出来的面试题。我们直接从0到1;往原理出发到实战来理解启动优化。

如何进行启动优化

冷启动

后台没有该应用的进程,这时系统会首先会创建一个新的进程分配给该应用 由于冷启动过程中,系统和APP的许多工作都要重新开始,所以一般而言这种启动方式是最慢且最具有挑战性的。除了创建和初始化Application和MainActivity之外,冷启动还要加载主题样式Theme,inflate布局,setContentView ,测量、布局、绘制以后显示,我们才看到了屏幕的第一帧。

也就是说当用户点击你的app那一刻到系统调用Activity.onCreate()之间的这个时间段内,WindowManager会先加载app主题样式中的windowBackground做为app的预览元素,然后再真正去加载activity的layout布局。

为什么会出现黑屏白屏呢?

系统进程在创建Application的过程中会产生一个BackgroudWindow,等到App完成了第一次绘制,系统进程才会用MainActivity的界面替换掉原来的BackgroudWindow。

很显然,如果你的application或activity启动的过程太慢,导致系统的BackgroundWindow没有及时被替换,就会出现启动时白屏或黑屏的情况(取决于你的主题是Dark还是Light)。

冷启动优化

1.主题替换

我们在style中自定义一个样式Lancher,在其中放一张背景图片,或是广告图片之类的

1. <style name="AppTheme.Launcher">  
​
2. <item name="android:windowBackground">@drawable/bg</item>  
​
3.  </style>  

把这个样式设置给启动的Activity

4. <activity  
​
5. android:name=".activity.SplashActivity"  
​
6. android:screenOrientation="portrait"  
​
7. android:theme="@style/AppTheme.Launcher"  
​
5.  >

然后在Activity的onCreate方法,把Activity设置回原来的主题

9. @Override  
​
10. protected void onCreate(Bundle savedInstanceState) {  
​
11. //替换为原来的主题,在onCreate之前调用  
​
12. setTheme(R.style.AppTheme);  
​
13. super.onCreate(savedInstanceState);  
​
6.  }  
​

这样在启动时就通过给用户看一张图片或是广告来防止黑白屏的尴尬。

还一种方式,就是把windowBackground属性设为null,这样在启动时,backgroundWindow的背景就会变成透明的,给人的感觉就是点了应用图标以后,延迟了一会儿然后加载第一个activity的界面。

1.  <style name="AppTheme.Launcher">  
2.  <item name="android:windowBackground">@null</item>  
3.  </style>

第二种方式可能会出现黑屏,第一种的图要选取好,不然也会有突兀感,所以很多公司都选择就让他白屏,改变主题实际上是一种伪优化,因为它实质上并没有真正减少App启动的时间 另外还可以设置style

<style name="LaunchStyle" parent="AppTheme">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowNoTitle">true</item>
</style>
或者
<item name="android:windowDisablePreview">true</item>
这个就是直接甩锅个系统

其他方法 就是进入后直接动画,或者是MD模式的效果, GitHub 上的开源项目 saulmm/onboarding-examples-android

Application是程序的主入口

延迟初始化,后台任务,界面预加载在Application的构造器方法、attachBaseContext()、onCreate()方法中不要进行耗时操作的初始化,一些数据预取放在异步线程中。

数据库,IO操作,密集网络请求不要放在Application的构造方法中,能使用工作线程的尽量使用工作线程,不要在Application的onCreate中创建线程池,因为那样会有比较大的开销,可以考虑延后再创建。 第三方SDK如果主线程中没有立即使用,可以考虑延迟几秒再初始化,总之一句话,尽早让用户看到应用的界面,其他操作都可以先让路。

对于MainActivity,由于在获取到第一帧前,需要对contentView进行测量布局绘制操作,尽量减少布局的层次,考虑StubView的延迟加载策略,当然在onCreate、onStart、onResume方法中避免做耗时操作

  • MultiDex以及Tinker的初始化,最先执行;关于MultiDex的优化本文不再赘述,参考我之前Multidex的系列文章。
  • Application中主要做了各种三方组件的初始化;

项目中除听云之外其余所有三方组件都抢占先机,在Application主线程初始化。这样的初始化方式肯定是过重的:

  • 考虑异步初始化三方组件,不阻塞主线程;
  • 延迟部分三方组件的初始化;实际上我们粗粒度的把所有三方组件都放到异步任务里,可能会出现WorkThread中尚未初始化完毕但MainThread中已经使用的错误,因此这种情况建议延迟到使用前再去初始化;
  • 而如何开启WorkThread同样也有讲究,这个话题在下文详谈。

项目修改:

  • 将友盟、Bugly、听云、GrowingIO、BlockCanary等组件放在WorkThread中初始化;
  • 延迟地图定位、ImageLoader、自有统计等组件的初始化:地图及自有统计延迟4秒,此时应用已经打开;而ImageLoader因为调用关系不能异步以及过久延迟,初始化从Application延迟到SplashActivity;而EventBus因为再Activity中使用所以必须在Application中初始化

2.温启动

一台已有该应用的进程,但是启动的入口Activity被干掉了,比如按了back键,应用虽然退出了,但是该应用的进程是依然会保留在后台

3.热启动

一后台已有该应用的进程,比如按下home键,这种在已有进程的情况下,这种启动会从已有的进程中来启动应用

应用的启动时间统计

在现在的公司最近还在搞启动优化,提供2种方式

1.查看启动时间adb 命令

adb shell am start -W [PackageName]/[PackageName.XX.XXXActivity] 这个PackageName 需要你到你自己项目的清单文件去自己找,输入adb命令后,程序会等待你启动然后在统计这个时间,

ThisTime:最后一个启动的Activity的启动耗时; ThisTime:一般和TotalTime时间一样,我们的是中间开了一个TotalTime:自己的所有Activity的启动耗时;包括创建进程+Application初始化+Activity初始化到界面显示WaitTime: ActivityManagerService启动App的Activity时的总时间(包括当前Activity的onPause()和自己Activity的启动)一般比TotalTime大点,包括系统影响的耗时

2.使用Android Studio 的日志,在过滤框输入display

然后清空日志,然后启动如下:

Application开始到首页显示出来

Application的构造器方法——>attachBaseContext()——>onCreate()——>Activity的构造方法——>onCreate()——>配置主题中背景等属性——>onStart()——>onResume()——>测量、布局、绘制显示在界面上

上面这些阶段全部都是在主线程中执行的,任何不经意的操作都可能拖慢应用的启动速度。所以我们不应在Application以及Activity的生命周期回调中做任何费时操作,具体指标大概是你在onCreate,onResume,onStart等回调中所花费的总时间最好不要超过400ms,否则用户在桌面点击你的应用图标后,将感觉到明显的卡顿

针对上面的需求,一般处理是将任务分优先级启动,应用启动开始加载 ;首页渲染后加载;渲染后延迟加载 具体延迟多久 在性能好的手机上面启动非常快,很短的延迟就行了,但是在低端手机上缺很慢,还要为了兼容久手机,一般延长很长的时间,

  第一种写法:直接PostDelay 300ms.
  myHandler.postDelayed(mLoadingRunnable, DEALY_TIME);
  第二种写法:优化的DelayLoad
  getWindow().getDecorView().post(new Runnable() {
    @Override
   public void run() {
        myHandler.post(mLoadingRunnable);
   }
  });

以上就是Android 性能优化的一些优化方式, Android启动优化更多的是一种优化思路,因为每个项目都不一样,导致优化的点也不一样,但掌握了优化思路可以以不变应万变。 有关更多 【Android核心技术 】及 【Android面试题】可以点击参考这个文档《Android核心技术与面试相关文档》;里面技术板块30几个面试文档50多个。

其他方案优化

1、UI渲染优化,去除重复绘制,减少UI重复绘制时间,打开设置中的GPU过度绘制开关,各界面过度绘制不应超过2.5x;也就是打开此调试开关后,界面整体呈现浅色,特别复杂的界面,红色区域也不应该超过全屏幕的四分之一;

2、根据优先级的划分,KoMobileApplication的一些初始化工作能否将任务优先级划分成3,在首页渲染完成后进行加载,比如:PaySDKManager。

3、主线程中的所有SharedPreference能否在非UI线程中进行,SharedPreferences的apply函数需要注意,因为Commit函数会阻塞IO,这个函数虽然执行很快,但是系统会有另外一个线程来负责写操作,当apply频率高的时候,该线程就会比较占用CPU资源。类似的还有统计埋点等,在主线程埋点但异步线程提交,频率高的情况也会出现这样的问题。

4、检查BaseActivity,不恰当的操作会影响所有子Activity的启动。

5、对于首次启动的黑屏问题,对于“黑屏”是否可以设计一个.9图片替换掉,间接减少用户等待时间。

6、对于网络错误界面,友好提示界面,使用ViewStub的方式,减少UI一次性绘制的压力。 7、Multidex的使用,也是拖慢启动速度的元凶,必须要做优化。后面有空专门写一篇Multidex。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/381022.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安全认证--JWT介绍及使用

安全认证--JWT介绍及使用1.无状态登录原理1.1.什么是有状态&#xff1f;1.2.什么是无状态1.3.如何实现无状态1.4.JWT1.4.1.简介1.4.2.数据格式2.编写JWT工具2.1.添加JWT依赖2.2.载荷对象2.3.工具2.4.测试2.4.1.配置秘钥2.4.2.测试类2.5项目源码1.无状态登录原理 有状态登录和无…

G1D54-CRF

一、CRF的输入X是什么&#xff1f;是构造的特征吗&#xff1f; 如此&#xff0c;CRF的x只用于状态函数吗&#xff1f; CRF的例子解释调用代码 机器之心 知乎忆榛 此处线性链条件随机场的特征函数形式被统一了&#xff1f; BilstmCRF&#xff0c;强烈推荐&#xff01;&#x…

AM402和SV660N、IS620N运动控制

软件&#xff1a;InoProShop(V1.7.3) 1、添加EtherCAT伺服从站 2、PLC运动控制程序和ETHERCAT在一个任务中。 3、编码器脉冲设置。 注意电机转速值是以秒还是分钟计量单位。 SV660N IS620N 4、设置电机停机方式。使用sin停机效果比较圆滑&#xff0c;默认梯形。 5、库管理器…

广和通携手联发科技正式发布基于MediaTek T830 平台5G模组FG370的可快速落地FWA解决方案

2月28日&#xff0c;全球领先的物联网无线通信解决方案和无线通信模组提供商广和通正式宣布&#xff1a;新一代5G模组FG370已率先实现量产&#xff0c;并于2023世界移动通信大会&#xff08;MWC Barcelona 2023&#xff09;期间携手联发科技正式发布基于FG370的FWA解决方案&…

十三、MyBatis的缓存

缓存&#xff1a;cache 缓存的作用&#xff1a;通过减少IO的方式&#xff0c;来提高程序的执行效率。 mybatis的缓存&#xff1a;将select语句的查询结果放到缓存&#xff08;内存&#xff09;当中&#xff0c;下一次还是这条select语句的话&#xff0c;直接从缓存中取&#xf…

数字信号复习题纲

数字信号复习题纲一、希尔伯特变换器&#xff08;:heavy_check_mark: &#xff09;1. 什么是希尔伯特变换器&#xff1f;2. 试证明信号通过希尔伯特变换器后的输出二、能量信号的自相关函数、卷积运算与能量谱&#xff08;:heavy_check_mark:&#xff09;1. 能量信号2. 试证明自…

webpack配置完全指南

前言 对于入门选手来讲&#xff0c;webpack 配置项很多很重&#xff0c;如何快速配置一个可用于线上环境的 webpack 就是一件值得思考的事情。其实熟悉 webpack 之后会发现很简单&#xff0c;基础的配置可以分为以下几个方面&#xff1a; entry 、 output 、 mode 、 resolve …

深入理解Storm 之 TridentStrom

从Demo讲起: FixedBatchSpout spout new FixedBatchSpout(new Fields("sentence"), 3, new Values("the cow jumped over the moon"),new Values("the man went to the store and bought some candy"),new Values("four score and seven …

新库上线 | CnOpenData中国债券市场债券信息数据

中国债券市场债券信息数据 一、数据简介 债券是政府、企业、银行等债务人为筹集资金&#xff0c;按照法定程序发行并向债权人承诺于指定日期还本付息的有价证券。债券购买者或投资者与发行者之间是一种债权债务关系&#xff0c;债券发行人即债务人&#xff0c;投资者&#xff…

关于 python 的异常使用说明 (python 的文件和异常)

文章目录异常1. 处理异常 ZeroDivisionError 异常2. 使用 try-except 代码块3. 使用异常避免崩溃4. else 代码块5. 处理 FileNotFoundError 异常6. 分析文本7. 失败时一声不吭异常 pyhong 使用被异常成为异常的特殊对象来管理程序执行期间发生的错误。 每当发生让 python 不知所…

【计算机网络:自顶向下方法】Chapter5 网络层:控制平面

本系列文章为笔者在学习b站中科大郑烇老师的计算机网络课程时&#xff08;郑老师讲得很清晰&#xff01;&#xff01;&#xff09;&#xff0c;结合课程PPT与《计算机网络&#xff1a;自顶向下方法》&#xff08;第七版&#xff09;所作的学习笔记&#xff0c;部分图片源自课程…

gitee 奇安信代码卫士使用

注册 gitee 账号后&#xff0c;push 一个项目&#xff0c;或者 fork 一个别人的项目&#xff0c;这里 fork 了一个 java-sec-code 靶场&#xff0c;使用的是个人版&#xff0c;像是低配版的 fortify 在项目的 服务 项下&#xff0c;选择奇安信代码卫士 创建分析 新建分析&…

【Java|golang】2373. 矩阵中的局部最大值

给你一个大小为 n x n 的整数矩阵 grid 。 生成一个大小为 (n - 2) x (n - 2) 的整数矩阵 maxLocal &#xff0c;并满足&#xff1a; maxLocal[i][j] 等于 grid 中以 i 1 行和 j 1 列为中心的 3 x 3 矩阵中的 最大值 。 换句话说&#xff0c;我们希望找出 grid 中每个 3 x …

操作系统笔记、面试八股(一)—— 进程、线程、协程

文章目录1. 进程、线程、协程1.1 进程1.1.1 进程间的通信方式1.1.2 进程同步方式1.1.3 进程的调度算法1.1.4 优先级反转1.1.5 进程状态1.1.6 PCB进程控制块1.1.7 进程的创建和撤销过程1.1.8 为什么要有进程1.2 线程1.2.1 为什么要有线程1.2.2 线程间的同步方式1.3 协程1.3.1 什…

创建Firebase项目并接入Firebase推送: Firebase Cloud Messaging (FCM)

1.FCM简介&#xff1a;Firebase Cloud Messaging (FCM) 是一种跨平台消息传递解决方案&#xff0c;可供您可靠地传递消息&#xff0c;而且还是免费的服务。支持 Android&#xff0c;IOS,Web,Flutter,Unity.消息类型可以使用 FCM 向客户端发送两种类型的消息&#xff1a;通知消息…

CEC2017:鱼鹰优化算法(Osprey optimization algorithm,OOA)求解cec2017(提供MATLAB代码)

一、鱼鹰优化算法简介 鱼鹰优化算法&#xff08;Osprey optimization algorithm&#xff0c;OOA&#xff09;由Mohammad Dehghani 和 Pavel Trojovsk于2023年提出&#xff0c;其模拟鱼鹰的捕食行为。 鱼鹰是鹰形目、鹗科、鹗属的仅有的一种中型猛禽。雌雄相似。体长51-64厘米…

Allegro如何设置铜皮避让的优先级操作指导

Allegro如何设置铜皮避让的优先级操作指导 在用Allegro进行PCB设计的时候,时常需要使用动态铜皮进行设计,当两块动态铜皮存在交集的时候,避让就会存在一个优先级,如下图 上方的铜皮避让调了下方的铜皮,上方的铜皮被避让了 如何调整让下方的铜皮避让上方的铜皮,如下图 具…

入门JAVA第十六天 数据库

一 、数据库技术学习内容与方法 1.1学习内容 1 Oracle 数据库 目前最好的关系型数据库 基本的CRUD命令。 SQL语句。select(R),update(U),detele(D),insert(C) 2 MySQL数据库 中小型醒目非常好用的关系型数据库。 灵活&#xff0c;小巧。 3 扩展软件开发流程中数据库设计原则 …

严格模式和非严格模式下的this指向问题

一、全局环境 1.函数调用 非严格模式&#xff1a;this指向是Window // 普通函数 function fn () { console.log(this, this); } fn() // 自执行函数 (function fn () { console.log(this, this); })() 严格模式&#xff1a;this指向是undefined //…

866363-70-4,N3-C5-NHS ester,叠氮-C5-NHS 主要物理性质分享

●外观以及性质&#xff1a;Azido-Aca-NHS淡黄色或无色油状&#xff0c;叠氮化物可以与炔烃、DBCO和BCN进行铜催化的点击化学反应。NHS酯可以与胺基反应&#xff0c;形成稳定的酰胺键。●中文名&#xff1a;叠氮-C5-NHS ester&#xff0c;6-叠氮己酸活性酯●英文名&#xff1a;…