Android面试常问一百题(第1题)——Android性能优化


Android性能优化往往成为了是否真正配得上高级开发的一道分水岭。性能优化也是近年来大厂面试频频问到的问题。


1. Android性能优化主要包括哪些方面?

:Android性能优化主要包括以下几个方面的优化:

  • 布局优化
  • 安装包优化
  • 网络优化
  • 内存优化
  • 卡顿优化
  • 启动优化
  • 绘制优化

2. 如何进行布局优化?

:布局优化的本质就是减少View的层级。在Android种系统对View进行测量、布局和绘制时,都是通过对View数的遍历来进行操作的。如果一个View数的高度太高就会严重影响测量、布局和绘制的速度。Google也在其API文档中建议View高度不宜超过10层。常见的布局优化方案如下:
(1)使用RelativeLayout替代LineraLayout作为默认根布局,目的就是降低LineraLayout嵌套产生布局树的高度,从而提高UI渲染的效率。
(2)使用 < include > 标签将常用的布局组件共同的部分抽取出来,以便复用。
(3)通过 < ViewStub > 标签来加载不常用的布局,延迟加载(需要的时候在activity中加载出来)
(4)使用 < Merge > 标签来减少布局的嵌套层次

3. 怎样进行安装包优化?

:安装包优化的核心就是减少apk的体积,常见的方案如下:

3.1 res资源优化:

(1)只使用一套图片,使用高分辨率的图片。
(2)UI设计在ps安装TinyPNG插件,对图片进行无损压缩。
(3)svg图片:一些图片的描述,牺牲CPU的计算能力的,节省空间。使用的原则:简单的图标。
(4)图片使用WebP(https://developers.google.com/speed/webp/)的格式(Facebook、腾讯、淘宝在用。)缺点:加载相比于PNG要慢很多。但是配置比较高。工具:http://isparta.github.io/
(5)使用tintcolor(android - Change drawable color programmatically)实现按钮反选效果。

3.2 代码优化:

(1)实现功能模块的逻辑简化
(2)Lint工具检查无用文件将无用的资源列在“UnusedResources: Unusedresources”,删除。
(3)移除无用的依赖库。

3.3 lib资源优化:

(1)动态下载的资源。
(2)一些模块的插件化动态添加。
(3)so文件的剪裁和压缩。

3.4 assets资源优化:

(1)音频文件最好使用有损压缩的格式,比如采用opus、mp3等格式,但是最好不要使用无损压缩的音乐格式
(2)对ttf字体文件压缩,可以采用FontCreator工具只提取出你需要的文字。比如在做日期显示时,其实只需要数字字体,但是使用原有的字体库可能需要10MB大小,如果只是把你需要的字体提取出来生成的字体文件只有10KB

3.5 代码混淆

3.6 使用proGuard 代码混淆器工具,它包括压缩、优化、混淆等功能。

3.7 插件化

3.8 可将功能模块放服务器,需要用时再加载。

3.9 7z极限压缩

4. 怎样进行网络优化?

:主要有:
(1)尽量减少网络请求,能够合并的就尽量合并
(2)避免DNS解析,根据域名查询可能会耗费上百毫秒的时间,也可能存在DNS劫持的风险。可以根据业务需求采用增加动态更新IP的方式,或者在IP方式访问失败时切换到域名访问方式。
(3)大量数据的加载采用分页的方式
(4)网络数据传输采用GZIP压缩
(5)加入网络数据的缓存,避免频繁请求网络
(6)上传图片时,在必要的时候压缩图片

5. 内存优化的方案?

:Android中的内存优化总的来说就是开源和节流,开源就是扩大内存,节流就是避免内存泄漏,内存泄漏的本质就是较长生命周期的对象引用了较短生命周期的对象。内存泄漏原因:堆上分配的对象已经不会再使用,但是GC收集器无法对其进行回收,此对象被强应用所引用 。

5.1 静态变量导致的内存泄漏

解决办法:将内部类设为静态内部类或独立出来;使用context.getApplicationContext()。

5.2 单例模式导致的内存泄漏

解决办法:传参context.getApplicationContext()。

5.3 属性动画导致的内存泄漏

解决办法:在Activity.onDestroy()中调用Animator.cancel()停止动画。

5.4 Handler导致的内存泄漏

解决办法:使用静态内部类+WeakReference弱引用;当外部类结束生命周期时清空消息队列。

5.5 线程导致的内存泄漏

解决办法:将AsyncTask和Runnable设为静态内部类或独立出来;在线程内部采用弱引用保存Context引用。

5.6 资源未关闭导致的内存泄漏

解决办法:在Activity销毁的时候要及时关闭或者注销。例如:
① BraodcastReceiver:调用unregisterReceiver()注销;
②Cursor,Stream、File:调用close()关闭;
③Bitmap:调用recycle()释放内存(2.3版本后无需手动)。

5.7 Adapter导致的内存泄漏

详情:不使用缓存而只依靠getView() 每次重新实例化Item,会给gc制造压力。
解决办法:在构造Adapter时使用缓存的convertView。

5.8 WebView导致的内存泄漏。

详情:WebView比较特殊,即使是调用了它的destroy方法,依然会导致内存泄漏。
解决办法:其实避免WebView导致内存泄漏的最好方法就是让WebView所在的Activity处于另一个进程中,当这个Activity结束时杀死当前WebView所处的进程即可,我记得阿里钉钉的WebView就是另外开启的一个进程,应该也是采用这种方法避免内存泄漏。

5.9 集合类泄漏

详情:比如全局map等有静态应用,最后没有做删除。
解决办法:在onDestry时回收不需要的集合。

5.10 扩大内存通常有两种方法:

一个是在清单文件中的Application下添加largeHeap="true"这个属性,另一个就是同一个应用开启多个进程来扩大一个应用的总内存空间。
第二种方法其实就很常见了,比方说我使用过个推的SDK,个推的Service其实就是处在另外一个单独的进程中。

6. 怎样进行卡顿优化?

:主要有:
(1)不要在主线程进行网络访问/大文件的IO操作
绘制UI时,尽量减少绘制UI层次;减少不必要的view嵌套,可以用Hierarchy Viewer工具来检测;
(2)当我们的布局是用的FrameLayout的时候,我们可以把它改成merge,可以避免自己的帧布局和系统的ContentFrameLayout帧布局重叠造成重复计算(measure和layout)
(3)提高显示速度,使用ViewStub:当加载的时候才会占用。不加载的时候就是隐藏的,仅仅占用位置。
(4)在view层级相同的情况下,尽量使用 LinerLayout而不是RelativeLayout;因为RelativeLayout在测量的时候会测量二次,而LinerLayout测量一次,可以看下它们的源码;
(5)删除控件中无用的属性;
(6)布局复用.比如listView 布局复用
(7)尽量避免过度绘制(overdraw),比如:背景经常容易造成过度绘制。由于我们布局设置了背景,同时用到的MaterialDesign的主题会默认给一个背景。这时应该把主题添加的背景去掉;还有移除
(8)XML 中非必须的背景
(9)自定义View优化。使用 canvas.clipRect()来帮助系统识别那些可见的区域,只有在这个区域内才会被绘制。也是避免过度绘制.
(10)启动优化,启动速度的监控,发现影响启动速度的问题所在,优化启动逻辑,提高应用的启动速度。比如闪屏页面,合理优化布局,加载逻辑优化,数据准备.
合理的刷新机制,尽量减少刷新次数,尽量避免后台有高的 CPU 线程运行,缩小刷新区域。

7. 说一下怎样进行启动优化?

:繁琐的Application 初始化:无论问题在于不必要的初始化还是磁盘I/O,解决方案都是延迟初始化。换句话说,你应该只初始化立即需要的对象。不要创建全局静态对象,而是转向单例模式,应用程序只在第一次需要时初始化对象。
此外,考虑使用依赖注入框架(如Hilt)

8. 如何进行绘制优化?

:包括两个方面:
(1)onDraw中不要创建新的局部对象。
因为onDraw方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统更加频繁gc,降低了程序的执行效率。
(2)onDraw方法中不要做耗时的任务,
不能执行成千上万次的循环操作,尽管每次循环都很轻量级,但是大量的循环仍然十分抢占CPU的时间片,这会造成View的绘制过程不流畅。
按照Google官方给出的性能优化典范中的标准,View的绘制频率保证60fps是最佳的,这就要求每帧绘制时间不超过16ms(16ms = 1000/60),虽然程序很难保证16ms这个时间,但是尽量降低onDraw方法中的复杂度总是切实有效的。

9. 说一说Android开发过程中性能优化所用到工具?

:(1)Memory Monitor : 它是Android Studio自带的一个内存监视工具,它可以很好地帮助我们进行内存实时分析。通过点击Android Studio右下角的Memory Monitor标签,打开工具可以看见较浅蓝色代表free的内存,而深色的部分代表使用的内存从内存变换的走势图变换,可以判断关于内存的使用状态,例如当内存持续增高时,可能发生内存泄漏;当内存突然减少时,可能发生GC等,如下图所示。

(2)LeakCanary: LeakCanary是Square公司基于MAT开发的一款监控Android内存泄漏的开源框架。其工作的原理是: 监测机制利用了Java的WeakReference和ReferenceQueue,通过将Activity包装到WeakReference中,被WeakReference包装过的Activity对象如果被回收,该WeakReference引用会被放到ReferenceQueue中,通过监测ReferenceQueue里面的内容就能检查到Activity是否能够被回收(在ReferenceQueue中说明可以被回收,不存在泄漏;否则,可能存在泄漏,LeakCanary是执行一遍GC,若还未在ReferenceQueue中,就会认定为泄漏)。

如果Activity被认定为泄露了,就抓取内存dump文件(Debug.dumpHprofData);之后通过HeapAnalyzerService.runAnalysis进行分析内存文件分析;接着通过HeapAnalyzer (checkForLeak—findLeakingReference—findLeakTrace)来进行内存泄漏分析。最后通过DisplayLeakService进行内存泄漏的展示。

(3)Lint : Android Lint Tool 是Android Sutido种集成的一个Android代码提示工具,它可以给你布局、代码提供非常强大的帮助。硬编码会提示以级别警告,例如:在布局文件中写了三层冗余的LinearLayout布局、直接在TextView中写要显示的文字、字体大小使用dp而不是sp为单位,就会在编辑器右边看到提示。

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iOS和Android测试是移动应用程序测试领域中非常重要的两个方面。在面试过程中,一些常见的问包括: 1. 你如何测试iOS和Android应用程序? 在测试iOS和Android应用程序时,首先要了解应用程序的功能需求和设计。然后使用相应的测试工具和设备,如Xcode和iOS模拟器进行iOS应用程序测试,使用Android Studio和模拟器进行Android应用程序测试。通过测试不同的功能和页面,包括用户界面、功能模块、设备兼容性和性能等方面,以确保应用程序的质量和稳定性。 2. 在iOS和Android应用程序测试中,你如何处理兼容性问? 在测试兼容性时,需要考虑不同版本的iOS和Android操作系统以及各种不同的设备。为了解决这个问,可以使用真实的设备进行测试,确保测试涵盖不同的操作系统版本和设备型号。此外,还可以利用各种移动测试工具,如Appium和Calabash等,来模拟并测试不同设备和操作系统环境下的应用程序。 3. 你在测试iOS和Android应用程序时使用哪些自动化测试工具? 在测试iOS和Android应用程序时,常用的自动化测试工具包括Appium、Calabash、KIF和Espresso等。这些工具可以自动化执行常见的测试任务,如界面操作、功能验证和性能测试等,并生成详细的测试报告。通过使用自动化工具,可以提高测试效率并减少测试人员的工作负担。 4. 如何测试应用程序的性能? 在测试应用程序的性能时,可以使用工具如Xcode Instruments和Android Profiler来监测应用程序的CPU、内存、网络和电池等方面的性能表现。同时,可以模拟不同的网络环境和设备压力来测试应用程序的性能稳定性。此外,还可以针对应用程序的不同功能和场景进行负载测试和压力测试,以验证其在高负载环境下的性能表现。 总而言之,测试iOS和Android应用程序需要综合考虑功能、兼容性和性能等方面的测试,并利用相应的测试工具和设备来保证应用程序的质量和用户体验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值