2019中级Android开发社招面试解答之性能优化篇

42 篇文章 1 订阅
35 篇文章 0 订阅

注:因为实际开发与参考答案会有所不同,再者怕误导大家,所以这些面试题答案还是自己去理解!面试官会针对简历中提到的知识点由浅入深提问,所以不要背答案,多理解。

1.图片的三级缓存中,图片加载到内存中,如果内存快爆了,会发生什么?怎么处理?
参考回答:
首先我们要清楚图片的三级缓存是如何的
在这里插入图片描述
如果内存足够时不回收。内存不够时就回收软引用对象

2.内存中如果加载一张500X500的png高清图片.应该是占用多少的内存?
参考回答:

  • 不考虑屏幕比的话:占用内存=500 * 500 * 4 = 1000000B ≈ 0.95MB
  • 考虑屏幕比的的话:占用内存= 宽度像素 x (inTargetDensity / inDensity) x 高度像素 x (inTargetDensity / inDensity)x 一个像素所占的内存字节大小
  • inDensity表示目标图片的dpi(放在哪个资源文件夹下),inTargetDensity表示目标屏幕的dpi
    在这里插入图片描述

3.WebView的性能优化 ?

参考回答:
一个加载网页的过程中,native、网络、后端处理、CPU都会参与,各自都有必要的工作和依赖关系;让他们相互并行处理而不是相互阻塞才可以让网页加载更快:

  • WebView初始化慢,可以在初始化同时先请求数据,让后端和网络不要闲着。
  • 常用 JS 本地化及延迟加载,使用第三方浏览内核
  • 后端处理慢,可以让服务器分trunk输出,在后端计算的同时前端也加载网络静态资源。
  • 脚本执行慢,就让脚本在最后运行,不阻塞页面解析。
  • 同时,合理的预加载、预缓存可以让加载速度的瓶颈更小。
  • WebView初始化慢,就随时初始化好一个WebView待用
  • DNS和链接慢,想办法复用客户端使用的域名和链接。
    在这里插入图片描述

4.Bitmap如何处理大图,如一张30M的大图,如何预防OOM?

参考回答:避免OOM的问题就需要对大图片的加载进行管理,主要通过缩放来减小图片的内存占用。

  • BitmapFactory提供的加载图片的四类方法(decodeFile、decodeResource、decodeStream、decodeByteArray)都支持BitmapFactory.Options参数,通过inSampleSize参数就可以很方便地对一个图片进行采样缩放
  • 比如一张10241024的高清图片来说。那么它占有的内存为102410244,即4MB,如果inSampleSize为2,那么采样后的图片占用内存只有512512*4,即1MB(注意:根据最新的官方文档指出,inSampleSize的取值应该总是为2的指数,即1、2、4、8等等,如果外界输入不足为2的指数,系统也会默认选择最接近2的指数代替,比如2)

综合考虑。通过采样率即可有效加载图片,流程如下

  • 将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片
  • 从BitmapFactory.Options中取出图片的原始宽高信息,它们对应outWidth和outHeight参数
  • 根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize
  • 将BitmapFactory.Options的inJustDecodeBounds参数设为false,重新加载图片
    在这里插入图片描述

5.内存回收机制与GC算法(各种算法的优缺点以及应用场景);GC原理时机以及GC对象
参考回答:
1.内存判定对象可回收有两种机制

  • 引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。然而在主流的Java虚拟机里未选用引用计数算法来管理内存,主要原因是它难以解决对象之间相互循环引用的问题,所以出现了另一种对象存活判定算法。
  • 可达性分析法:通过一系列被称为『GCRoots』的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。其中可作为GC Roots的对象:虚拟机栈中引用的对象,主要是指栈帧中的本地变量*、本地方法栈中Native方法引用的对象、方法区中类静态属性引用的对象、方法区中常量引用的对象

2.GC回收算法有以下四种:

  • 分代收集算法:是当前商业虚拟机都采用的一种算法,根据对象存活周期的不同,将Java堆划分为新生代和老年代,并根据各个年代的特点采用最适当的收集算法。

  • 新生代:大批对象死去,只有少量存活。使用『复制算法』,只需复制少量存活对象即可

    • 复制算法:把可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用尽后,把还存活着的对象『复制』到另外一块上面,再将这一块内存空间一次清理掉。实现简单,运行高效。在对象存活率较高时就要进行较多的复制操作,效率将会变低
  • 老年代:对象存活率高。使用『标记—清理算法』或者『标记—整理算法』,只需标记较少的回收对象即可。

    • 标记-清除算法:首先『标记』出所有需要回收的对象,然后统一『清除』所有被标记的对象。标记和清除两个过程的效率都不高,清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
    • 标记-整理算法:首先『标记』出所有需要回收的对象,然后进行『整理』,使得存活的对象都向一端移动,最后直接清理掉端边界以外的内存。标记整理算法会将所有的存活对象移动到一端,并对不存活对象进行处理,因此其不会产生内存碎片

6.内存泄露和内存溢出的区别 ?AS有什么工具可以检测内存泄露
参考回答:

  • 内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
  • 内存泄露(memory leak):是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。memory leak会最终会导致out of memory!
  • 查找内存泄漏可以使用Android Studio 自带的AndroidProfiler工具或MAT

7.性能优化,怎么保证应用启动不卡顿? 黑白屏怎么处理?
参考回答:

  • 应用启动速度,取决于你在application里面时候做了什么事情,比如你集成了很多sdk,并且sdk的init操作都需要在主线程里实现所以会有卡顿的感觉。在非必要的情况下可以把加载延后或则开启子线程处理

  • 另外,影响界面卡顿的两大因素,分别是界面绘制和数据处理。

    • 布局优化(使用include,merge标签,复杂布局推荐使用ConstraintLayout等)
    • onCreate() 中不执行耗时操作 把页面显示的 View 细分一下,放在 AsyncTask 里逐步显示,用 Handler 更好。这样用户的看到的就是有层次有步骤的一个个的 View 的展示,不会是先看到一个黑屏,然后一下显示所有 View。最好做成动画,效果更自然。
    • 利用多线程的目的就是尽可能的减少 onCreate() 和 onReume() 的时间,使得用户能尽快看到页面,操作页面。
    • 减少主线程阻塞时间。
    • 提高 Adapter 和 AdapterView 的效率。
  • 黑白屏产生原因:当我们在启动一个应用时,系统会去检查是否已经存在这样一个进程,如果不存在,系统的服务会先检查startActivity中的intent的信息,然后在去创建进程,最后启动Acitivy,即冷启动。而启动出现白黑屏的问题,就是在这段时间内产生的。系统在绘制页面加载布局之前,首先会初始化窗口(Window),而在进行这一步操作时,系统会根据我们设置的Theme来指定它的Theme 主题颜色,我们在Style中的设置就决定了显示的是白屏还是黑屏。

    • windowIsTranslucent和windowNoTitle,将这两个属性都设置成true (会有明显的卡顿体验,不推荐)
    • 如果启动页只是是一张图片,那么为启动页专一设置一个新的主题,设置主题的android:windowBackground属性为启动页背景图即可
    • 使用layer-list制作一张图片launcher_layer.xml,将其设置为启动页专一主题的背景,并将其设置为启动页布局的背景

8.强引用置为null,会不会被回收?

参考回答:

不会立即释放对象占用的内存。 如果对象的引用被置为null,只是断开了当前线程栈帧中对该对象的引用关系,而 垃圾收集器是运行在后台的线程,只有当用户线程运行到安全点(safe point)或者安全区域才会扫描对象引用关系,扫描到对象没有被引用则会标记对象,这时候仍然不会立即释放该对象内存,因为有些对象是可恢复的(在 finalize方法中恢复引用 )。只有确定了对象无法恢复引用的时候才会清除对象内存。

9.ListView跟RecyclerView的区别
参考回答:
动画区别:

  • 在RecyclerView中,内置有许多动画API,例如:notifyItemChanged(), notifyDataInserted(), notifyItemMoved()等等;如果需要自定义动画效果,可以通过实现(RecyclerView.ItemAnimator类)完成自定义动画效果,然后调用RecyclerView.setItemAnimator();

  • 但是ListView并没有实现动画效果,但我们可以在Adapter自己实现item的动画效果;

刷新区别:

  • ListView中通常刷新数据是用全局刷新notifyDataSetChanged(),这样一来就会非常消耗资源;本身无法实现局部刷新,但是如果要在ListView实现局部刷新,依然是可以实现的,当一个item数据刷新时,我们可以在Adapter中,实现一个onItemChanged()方法,在方法里面获取到这个item的position(可以通过getFirstVisiblePosition()),然后调用getView()方法来刷新这个item的数据;
  • RecyclerView中可以实现局部刷新,例如:notifyItemChanged();

缓存区别:

  • RecyclerView比ListView多两级缓存,支持多个离ItemView缓存,支持开发者自定义缓存处理逻辑,支持所有RecyclerView共用同一个RecyclerViewPool(缓存池)。
  • ListView和RecyclerView缓存机制基本一致,但缓存使用不同

10.ListView的adapter是什么adapter
参考回答:
在这里插入图片描述

  • BaseAdapter:抽象类,实际开发中我们会继承这个类并且重写相关方法,用得最多的一个适配器!
  • ArrayAdapter:支持泛型操作,最简单的一个适配器,只能展现一行文字〜
  • SimpleAdapter:同样具有良好扩展性的一个适配器,可以自定义多种效果!
  • SimpleCursorAdapter:用于显示简单文本类型的listView,一般在数据库那里会用到,不过有点过时,不推荐使用!

11.LinearLayout、FrameLayout、RelativeLayout性能对比,为什么?
参考回答:

  • RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,也会调用子 View 2次onMeasure
  • RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题,当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin。
  • 在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout。

到此。性能优化篇就完结了,如果需要查找更多面试内容和Android相关内容可以查看我的主页
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当然,我会为您提供10道Android性能优化相关的中级面试笔试题,每道题都附有答案和解析,以下是题目: 1. 请简述Android应用性能优化的主要方向是什么?给出至少两个例子。 答案:Android应用性能优化的主要方向是获取更高的CPU、内存、网络和能源利用率。两个例子如下: (1) 缓存技术:使用缓存技术可以减少网络请求,提高数据读取的速度。 (2) 懒加载:对于大型图像或其他资源,我们可以采用懒加载的方式,即在用户需要时才加载,避免了不必要的消耗。 2. 请问在使用Android布局优化时,我们需要考虑哪些因素? 答案:在使用Android布局优化时,我们需要考虑以下因素: (1) 嵌套深度:减少嵌套深度,避免过多的View Group。 (2) 布局重用:尽量复用布局,避免重复编写。 (3) 尺寸限制:尺寸设定要合理,不要设置过多的match_parent,wrap_content属性。 3. 请简述Android内存泄漏的概念,并给出一个例子。 答案:Android内存泄漏指的是在应用程序中因为某种原因而导致Android系统无法回收该应用程序占用的内存,最终导致应用程序崩溃。一个例子是:内部类、单例类、Activity与生命周期不同步等都可能导致Android内存泄漏。 4. 请问在Android性能优化中,你是如何使用异步编程的? 答案:在Android性能优化中,我们通常会使用异步编程。异步编程是一种高效的方式,它可以避免在主线程中执行耗时操作而导致的UI卡顿。在Android平台上,我们可以使用AsyncTask等来实现异步编程。 5. 请简述Android多线程优化的一些技巧。 答案:Android多线程优化的一些技巧包括: (1) 使用线程池:避免频繁地创建和销毁线程。 (2) 使用Handler机制:避免在子线程中直接修改UI。 (3) 合理设置线程优先级:避免线程饥饿。 (4) 避免过度同步:避免不必要的锁的竞争。 6. 请问在Android网络编程中,如何优化网络请求的性能? 答案:在Android网络编程中,我们可以采取以下措施来优化网络请求的性能: (1) 合理设置超时时间:避免网络请求时间过长。 (2) 合理选择网络请求方式:根据不同情况选择适合的网络请求方式,如使用POST请求替代GET请求。 (3) 多任务并行执行:充分利用并行执行的优点,提高网络请求效率。 (4) 数据缓存:使用数据缓存,避免重复请求数据。 7. 请问在Android图片处理中,如何优化图片加载的性能? 答案:在Android图片处理中,我们可以采取以下措施来优化图片加载的性能: (1) 使用适当的图片格式:选择适合的图片格式,如PNG、JPEG等。 (2) 压缩图片:压缩图片大小,减少图片在网络传输和解析的时间。 (3) 图片缓存:使用图片缓存,避免重复加载图片。 (4) 使用懒加载:在用户需要时才加载图片,避免不必要的消耗。 8. 请问在Android能源优化中,你是如何采取措施的? 答案:在Android能源优化中,我们可以采取以下措施: (1) 降低CPU功耗:避免使用高功耗的组件,如高像素的屏幕、高频率的网络访问等。 (2) 降低屏幕功耗:降低屏幕亮度、关闭自动亮度调节。 (3) 合理使用传感器:避免滥用传感器,如陀螺仪、加速度计等。 (4) 停用不必要的服务:停用不必要的服务,如GPS、蓝牙等。 9. 请问在Android代码规范中,应该遵循哪些格式要求? 答案:在Android代码规范中,我们应该遵循以下格式要求: (1) 缩进:使用4个空格作为缩进。 (2) 换行:每行代码不应超过120个字符。 (3) 注释:添加必要的注释,增加代码可读性。 (4) 命名:命名要具有良好的可读性,要求见名知意。 10. 请问在Android安全性优化中,需要采取哪些措施? 答案:在Android安全性优化中,我们需要采取以下措施: (1) 加密:对于用户数据和敏感信息,使用加密措施保护安全。 (2) 弱密码防范:强制要求用户输入较为复杂的密码,限制密码的长度和不允许使用弱密码。 (3) 安全风险接口:限制危险的API接口,防止黑客攻击或恶意操作。 (4) 安全存储:确保用户数据和应用程序数据存储在安全的存储器中,如内部存储和外部存储。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值