金三银四Android 开发到底该刷那些题?方向在哪?

一年一度的金三银四面试旺季,是面试者们比较关心的一个时机。因为大家都希望在这个面试旺季实现自己的跳槽涨薪的机会,又往往担心自己在面试时被面试官的题目带进坑,于是想在网上找面试题前开始刷,但又不知到方向在哪?小编正好想到这件事,想来做次活雷锋。特此将一些往年面试题进行了整理,为大家指引方向,助力大家在面试途中一臂之力,太多废话不多说了,请看题……

设计模式

1、你所知道的设计模式有哪些?

  • 参考回答:
    • 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
    • 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
    • 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录 模式、状态模式、访问者模式、中介者模式、解释器模式

2、谈谈 MVC、MVP 和 MVVM,好在哪里,不好在哪里 ?

  • 参考回答:
    • MVC:

      • 视图层(View) 对应于 xml 布局文件和 java 代码动态view 部分
      • 控制层(Controller) MVC 中 Android 的控制层是由Activity 来承担的,Activity 本来主要是作为初始化页
        面,展示数据的操作,但是因为 XML 视图功能太弱,所以 Activity 既要负责视图的显示又要加入控制逻辑,承担的功能过多。
      • 模型层(Model) 针对业务模型,建立数据结构和相关的类,它主要负责网络请求,数据库处理,I/O 的操作。
    • 总结

      • 具有一定的分层,model 彻底解耦,controller 和 view并没有解耦层与层之间的交互尽量使用回调或者去使用消息机制去完成,尽量避免直接持有 controller 和 view 在 android 中无法做到彻底分离,但在代码逻辑层面一定要分清业务逻辑被放置在 model 层,能够更好的复用和修改增加业务。
    • MVP

      • 通过引入接口 BaseView,让相应的视图组件如Activity,Fragment 去实现 BaseView,实现了视图层
        的独立,通过中间层 Preseter 实现了 Model 和 View 的完全解耦。MVP 彻底解决了 MVC 中 View 和 Controller 傻傻分不清楚的问题,但是随着业务逻辑的增加,一个页面可能会非常复杂,UI 的改变是非常多,会有非常多的 case,这样就会造成 View 的接口会很庞大。
    • MVVM

      • MVP 中我们说过随着业务逻辑的增加,UI 的改变多的情况下,会有非常多的跟 UI 相关的 case,这样就会造成 View 的接口会很庞大。而 MVVM 就解决了这个问题,通过双向绑定的机制,实现数据和 UI 内容,只要想改其中一方,另一方都能够及时更新的一种设计理念,这样就省去了很多在 View 层中写很多 case 的情况,只需要改变数据就行。
    • 三者如何选择?

      • 如果项目简单,没什么复杂性,未来改动也不大的话,那就不要用设计模式或者架构方法,只需要将每个模块封装好,方便调用即可,不要为了使用设计模式或架构方法而使用。
      • 对于偏向展示型的 app,绝大多数业务逻辑都在后端,app 主要功能就是展示数据,交互等,建议使用
        mvvm。
      • 对于工具类或者需要写很多业务逻辑 app,使用 mvp或者 mvvm 都可。

3、封装 p 层之后.如果 p 层数据过大,如何解决?

  • 参考回答:
    • 对于 MVP 模式来说,P 层如果数据逻辑过于臃肿,建议引入RxJava 或则 Dagger,越是复杂的逻辑,越能体现 RxJava 的优越性。

4、是否能从 Android 中举几个例子说说用到了什么设计模式 ?

  • 参考回答:
    • AlertDialog、Notification 源码中使用了 Builder(建造者)模式完成参数的初始化
    • Okhttp 内部使用了责任链模式来完成每个 Interceptor 拦截器的调用
    • RxJava 的观察者模式;单例模式;GridView 的适配器模式;Intent 的原型模式
    • 日常开发的 BaseActivity 抽象工厂模式

5、装饰模式和代理模式有哪些区别 ?

  • 参考回答:
    • 装饰器模式与代理模式的区别就在于
      • 两者都是对类的方法进行扩展,但装饰器模式强调的是增强自身,在被装饰之后你能够在被增强的类上使用增强后的功能
      • 而代理模式则强调要让别人帮你去做一些本身与你业务没有太多关系的职责(记录日志、设置缓存)代理模式是为了实现对象的控制,因为被代理的对象往往难以直接获得或者是其内部不想暴露出来

6、实现单例模式有几种方法 ?懒汉式中双层锁的目的是什么 ?两次判空的目的又是什么 ?

  • 参考回答:
    • 单例模式实现方法有多种:饿汉,懒汉(线程安全,线程非安全),双重检查(DCL),内部类,以及枚举
    • 所谓双层检验锁(在加锁前后对实例对象进行两次判空的检验):加锁是为了第一次对象实例化的线程同步,而锁内还要有第二层判空是因为可能会有多个线程进入第一层 if 判断内部,而在加锁代码块外排队等候,如果锁内不进行第二次检验,仍然会出现实例化多个对象的情况。

7、用到的一些开源框架,介绍一个看过源码的,内部实现过程。

  • 参考回答:
    • 面试常客:Okhttp,Retrofit,Glide,RxJava,GreenDao,Dagger 等。

8、Fragment 如果在 Adapter 中使用应该如何解耦?

  • 参考回答:
    • 接口回调
    • 广播

性能优化

1、图片的三级缓存中,图片加载到内存中,如果内存快爆了,会发生什么?怎么处

理?

  • 参考回答:
    • 首先我们要清楚图片的三级缓存是如何的

如果内存足够时不回收。内存不够时就回收软引用对象

2、内存中如果加载一张 500*500 的 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?

5、内存回收机制与 GC 算法(各种算法的优缺点以及应用场景);GC 原理时机以及 GC 对象

6、内存泄露和内存溢出的区别 ?AS 有什么工具可以检测内存泄露

7、性能优化,怎么保证应用启动不卡顿? 黑白屏怎么处理?

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

9、ListView 跟 RecyclerView 的区别

10、ListView 的 adapter 是什么 adapter

11、LinearLayout、FrameLayout、RelativeLayout 性能对比,为什么?

Android 面试知识点大全

Android 进阶延伸点

1、如何进行单元测试,如何保证 App 稳定 ?

  • 参考回答:
    要测试 Android 应用程序,通常会创建以下类型自动单元测试
    • 本地测试:只在本地机器 JVM 上运行,以最小化执行时间,这种单元测试不依赖于 Android 框架,或
      者即使有依赖,也很方便使用模拟框架来模拟依赖,以达到隔离 Android 依赖的目的,模拟框架如
      Google 推荐的 Mockito;
    • 检测测试:真机或模拟器上运行的单元测试,由于需要跑到设备上,比较慢,这些测试可以访问仪器(Android 系统)信息,比如被测应用程序的上下文,一般地,依赖不太方便通过模拟框架模拟时采用这种方式;
  • 注意:单元测试不适合测试复杂的 UI 交互事件
  • App 的稳定主要决定于整体的系统架构设计,同时也不可忽略代码编程的细节规范,正所谓“千里之堤,溃于蚁穴”,一旦考虑不周,看似无关紧要的代码片段可能会带来整体软件系统的崩溃,所以上线之前除了自己本地化测试之外还需要进行 Monkey 压力测试
  • 少部分面试官可能会延伸,如 Gradle 自动化测试、机型适配测试等

2、Android 中如何查看一个对象的回收情况 ?

  • 参考回答:
    • 首先要了解 Java 四种引用类型的场景和使用(强引用、软引用、弱引用、虛引用)
    • 举个场景例子:SoftReference 对象是用来保存软引用的,但它同时也是一个 Java 对象,所以当软引用对象被回收之后,虽然这个 SoftReference 对象的 get 方法返回 null,但 SoftReference 对象本身并不是 null,而此时这个 SoftReference 对象已经不再具有存在的价值,需要一个适当的清除机制,避免大量 SoftReference 对象带来的内存泄露
    • 因此,Java 提供 ReferenceQueue 来处理引用对象的回收情况。当 SoftReference 所引用的对象被 GC 后,JVM 会先将 softReference 对象添加到 ReferenceQueue 这个队列中。当我们调用 ReferenceQueue 的 poll()方法,如果这个队列中不是空队列,那么将返回并移除前面添加的那个Reference 对象。

3、Apk 的大小如何压缩 ?

  • 参考回答:
    • 一个完整 APK 包含以下目录(将 APK 文件拖到 Android Studio):

      • META-INF/:包含 CERT.SF 和 CERT.RSA 签名文件以及 MANIFEST.MF 清单文件。
      • assets/:包含应用可以使用 AssetManager 对象检索的应用资源。
      • res/:包含未编译到的资源 resources.arsc。
      • lib/:包含特定于处理器软件层的编译代码。该目录包含了每种平台的子目录,像 armeabi,armeabi-v7a, arm64-v8a,x86,x86_64,和mips。
      • resources.arsc:包含已编译的资源。该文件包含 res/values/ 文件夹所有配置中的 XML 内容。打包工具提取此 XML 内容,将其编译为二进制格式,并将内容归档。此内容包括语言字符串和样式,以及直接包含在** resources.arsc*8 文件中的内容路径 ,例如布局文件和图像。
      • classes.dex:包含以 Dalvik / ART 虚拟机可理解的 DEX 文件格式编译的类。
      • AndroidManifest.xml:包含核心 Android 清单文件。该文件列出应用程序的名称,版本,访问权限和引用的库文件。该文件使用 Android 的二进制XML 格式。
      • lib、class.dex 和 res 占用了超过 90%的空间,所以这三块是优化 Apk 大小的重点(实际情况不唯一)
    • 减少 res,压缩图文文件

      • 图片文件压缩是针对 jpg 和 png 格式的图片。我们通常会放置多套不同分辨率的图片以适配不同的屏幕,这里可以进行适当的删减。在实际使用中,只保留一到两套就足够了(保留一套的话建议保留 xxhdpi,两套的话就加上 hdpi),然后再对剩余的图片进行压缩(jpg 采用优图压缩,png 尝试采用pngquant 压缩)
    • 减少 dex 文件大小

      • 添加资源混淆
      • shrinkResources 为 true 表示移除未引用资源,和代码压缩协同工作。
      • minifyEnabled 为 true 表示通过 ProGuard 启用代码压缩,配合 proguardFiles 的配置对代码进行混淆并移除未使用的代码。
      • 代码混淆在压缩 apk 的同时,也提升了安全性。
    • 减少 lib 文件大小

      • 由于引用了很多第三方库,lib 文件夹占用的空间通常都很大,特别是有 so 库的情况下。很多 so 库会同时引入 armeabi、armeabi-v7a 和 x86 这几种类型,这里可以只保留 armeabi 或 armeabi-v7a 的其中一个就可以了,实际上微信等主流 app 都是这么做的。
      • 只需在 build.gradle 直接配置即可,NDK 配置同理

4、如何通过 Gradle 配置多渠道包?

  • 参考回答:
    • 首先要了解设置多渠道的原因。在安装包中添加不同的标识,配合自动化埋点,应用在请求网络的时候携带渠道信息,方便后台做运营统计,比如说统计我们的应用在不同应用市场的下载量等信息
    • 这里以友盟统计为例
      • 首先在 manifest.xml 文件中设置动态渠道变量:
      • 接着在 app 目录下的 build.gradle 中配置productFlavors,也就是配置打包的渠道:
      • 最后在编辑器下方的 Teminal 输出命令行
        • 执行./gradlew assembleRelease ,将会打出所有渠道的 release 包;
        • 执行./gradlew assembleVIVO,将会打出VIVO 渠道的 release 和 debug 版的包;
        • 执行./gradlew assembleVIVORelease 将生成 VIVO 的 release 包。
          5、插件化原理分析
          6、组件化原理
          7、组件化中路由、埋点的实现
          8、Hook 以及插桩技术
          9、请例举 Android 中常用布局类型,并简述其用法以及排版效率
          10、区别 Animation 和 Animator 的用法,概述其原理
          11、使用过什么图片加载库?Glide 的源码设计哪里很微妙?
          12、用过哪些网络加载库?OkHttp、Retrofit 实现原理?
          13、对于应用更新这块是如何做的? (灰度,强制更新、分区域更新)
          14、会用 Kotlin、Fultter 吗? 谈谈你的理解

Android 面试知识点大全

最后

因为文章篇幅长度有限制,暂且只能分享到这了。但小编利用闲暇时刻,将Android 相关更多的面试题及答案收集整理了PDF文档形式,并上传之GitHub中,如果大家想参考学习Android 相关面试题及一些知识点可以直接去我 GitHub 项目地址:https://github.com/733gh/Android-T3 中进行查看。

猜你喜欢

转载自blog.csdn.net/dongrimaomaoyu/article/details/114042788