2019最新Android中级面试题目汇总解答

文章来源:安卓巴士

Android进阶延伸点面试

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

参考回答:安全

要测试Android应用程序,一般会建立如下类型自动单元测试微信

  • 本地测试:只在本地机器JVM上运行,以最小化执行时间,这种单元测试不依赖于Android框架,或者即便有依赖,也很方便使用模拟框架来模拟依赖,以达到隔离Android依赖的目的,模拟框架如Google推荐的Mockito;
  • 检测测试:真机或模拟器上运行的单元测试,因为须要跑到设备上,比较慢,这些测试能够访问仪器(Android系统)信息,好比被测应用程序的上下文,通常地,依赖不太方便经过模拟框架模拟时采用这种方式;

注意:单元测试不适合测试复杂的UI交互事件网络

App的稳定主要决定于总体的系统架构设计,同时也不可忽略代码编程的细节规范,正所谓“千里之堤,溃于蚁穴”,一旦考虑不周,看似可有可无的代码片断可能会带来总体软件系统的崩溃,因此上线以前除了本身本地化测试以外还须要进行Monkey压力测试架构

少部分面试官可能会延伸,如Gradle自动化测试、机型适配测试等app

2.Android中如何查看一个对象的回收状况 ?框架

参考回答:编辑器

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

3.Apk的大小如何压缩 ?工具

参考回答:

3.1一个完整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.arsc8文件中的内容路径 ,例如布局文件和图像。
  • classes.dex:包含以Dalvik / ART虚拟机可理解的DEX文件格式编译的类。
  • AndroidManifest.xml:包含核心Android清单文件。该文件列出应用程序的名称,版本,访问权限和引用的库文件。该文件使用Android的二进制XML格式。


2019最新Android中级面试题目汇总解答


  • lib、class.dex和res占用了超过90%的空间,因此这三块是优化Apk大小的重点(实际状况不惟一)

3.2.减小res,压缩图文文件

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

3.3.减小dex文件大小

  • 添加资源混淆

2019最新Android中级面试题目汇总解答


  • shrinkResources为true表示移除未引用资源,和代码压缩协同工做。
  • minifyEnabled为true表示经过ProGuard启用代码压缩,配合proguardFiles的配置对代码进行混淆并移除未使用的代码。
  • 代码混淆在压缩apk的同时,也提高了安全性。

3.4.减小lib文件大小

  • 因为引用了不少第三方库,lib文件夹占用的空间一般都很大,特别是有so库的状况下。不少so库会同时引入armeabi、armeabi-v7a和x86这几种类型,这里能够只保留armeabi或armeabi-v7a的其中一个就能够了,实际上微信等主流app都是这么作的。
  • 只需在build.gradle直接配置便可,NDK配置同理


2019最新Android中级面试题目汇总解答


4.如何经过Gradle配置多渠道包?

参考回答:

首先要了解设置多渠道的缘由。在安装包中添加不一样的标识,配合自动化埋点,应用在请求网络的时候携带渠道信息,方便后台作运营统计,好比说统计咱们的应用在不一样应用市场的下载量等信息

  • 这里以友盟统计为例
  • 首先在manifest.xml文件中设置动态渠道变量:

2019最新Android中级面试题目汇总解答


  • 接着在app目录下的build.gradle中配置productFlavors,也就是配置打包的渠道:

2019最新Android中级面试题目汇总解答


  • 最后在编辑器下方的Teminal输出命令行
  1. 执行./gradlew assembleRelease ,将会打出全部渠道的release包;
  2. 执行./gradlew assembleVIVO,将会打出VIVO渠道的release和debug版的包;
  3. 执行./gradlew assembleVIVORelease将生成VIVO的release包。

5.插件化原理分析

参考回答:

插件化是指将 APK 分为宿主和插件的部分。把须要实现的模块或功能当作一个独立的提取出来,在 APP 运行时,咱们能够动态的载入或者替换插件部分,减小宿主的规模

  • 宿主: 就是当前运行的APP。
  • 插件: 相对于插件化技术来讲,就是要加载运行的apk类文件。

而热修复则是从修复bug的角度出发,强调的是在不须要二次安装应用的前提下修复已知的bug。能


2019最新Android中级面试题目汇总解答


类加载机制

Android中经常使用的两种类加载器,DexClassLoader和PathClassLoader,它们都继承于BaseDexClassLoader,二者区别在于PathClassLoader只能加载内部存储目录的dex/jar/apk文件。DexClassLoader支持加载指定目录(不限于内部)的dex/jar/apk文件

插件通讯:经过给插件apk生成相应的DexClassLoader即可以访问其中的类,可分为单DexClassLoader和多DexClassLoader两种结构。

  • 若使用多ClassLoader机制,主工程引用插件中类须要先经过插件的ClassLoader加载该类再经过反射调用其方法。插件化框架通常会经过统一的入口去管理对各个插件中类的访问,而且作必定的限制。
  • 若使用单ClassLoader机制,主工程则能够直接经过类名去访问插件中的类。该方式有个弊端,若两个不一样的插件工程引用了一个库的不一样版本,则程序可能会出错

资源加载

  • 原理在于经过反射将插件apk的路径加入AssetManager中并建立Resource对象加载资源,有两种处理方式:
  • 合并式:addAssetPath时加入全部插件和主工程的路径;因为AssetManager中加入了全部插件和主工程的路径,所以生成的Resource能够同时访问插件和主工程的资源。可是因为主工程和各个插件都是独立编译的,生成的资源id会存在相同的状况,在访问时会产生资源冲突。
  • 独立式:各个插件只添加本身apk路径,各个插件的资源是互相隔离的,不过若是想要实现资源的共享,必须拿到对应的Resource对象。

6.组件化原理

参考回答:

引入组件化的缘由:项目随着需求的增长规模变得愈来愈大,规模的增大致使了各类业务错中复杂的交织在一块儿, 每一个业务模块之间,代码没有约束,带来了代码边界的模糊,代码冲突时有发生, 更改一个小问题可能引发一些新的问题, 牵一发而动全身,增长一个新需求,须要熟悉相关的代码逻辑,增长开发时间

  • 避免重复造轮子,能够节省开发和维护的成本。
  • 能够经过组件和模块为业务基准合理地安排人力,提升开发效率。
  • 不一样的项目能够共用一个组件或模块,确保总体技术方案的统一性。
  • 为将来插件化共用同一套底层模型作准备。

组件化开发流程就是把一个功能完整的App或模块拆分红多个子模块(Module),每一个子模块能够独立编译运行,也能够任意组合成另外一个新的 App或模块,每一个模块即不相互依赖但又能够相互交互,可是最终发布的时候是将这些组件合并统一成一个apk,遇到某些特殊状况甚至能够升级或者降级

举个简单的模型例子


2019最新Android中级面试题目汇总解答


2019最新Android中级面试题目汇总解答


App是主application,ModuleA和ModuleB是两个业务模块(相对独立,互不影响),Library是基础模块,包含全部模块须要的依赖库,以及一些工具类:如网络访问、时间工具等

注意:提供给各业务模块的基础组件,须要根据具体状况拆分红 aar 或者 library,像登陆,基础网络层这样较为稳定的组件,通常直接打包成 aar,减小编译耗时。而像自定义 View 组件,因为随着版本迭代会有较多变化,就直接以源码形式抽离成 Library

7.跨组件通讯

参考回答:

7.1.跨组件通讯场景:

  • 第一种是组件之间的页面跳转 (Activity 到 Activity, Fragment 到 Fragment, Activity 到 Fragment, Fragment 到 Activity) 以及跳转时的数据传递 (基础数据类型和可序列化的自定义类类型)。
  • 第二种是组件之间的自定义类和自定义方法的调用(组件向外提供服务)。

7.2.跨组件通讯方案分析:

  • 第一种组件之间的页面跳转实现简单,跳转时想传递不一样类型的数据提供有相应的 API便可
  • 第二种组件之间的自定义类和自定义方法的调用要稍微复杂点,须要 ARouter 配合架构中的 公共服务(CommonService) 实现:
  • 提供服务的业务模块:

  • 在公共服务(CommonService) 中声明 Service 接口 (含有须要被调用的自定义方法), 而后在本身的模块中实现这个 Service 接口, 再经过 ARouter API 暴露实现类。

  • 使用服务的业务模块:
  • 经过 ARouter 的 API 拿到这个 Service 接口(多态持有, 实际持有实现类), 便可调用 Service 接口中声明的自定义方法, 这样就能够达到模块之间的交互。
  • 此外,可使用 AndroidEventBus 其独有的 Tag, 能够在开发时更容易定位发送事件和接受事件的代码, 若是以组件名来做为 Tag 的前缀进行分组, 也能够更好的统一管理和查看每一个组件的事件, 固然也不建议你们过多使用 EventBus。

7.3.如何管理过多的路由表?

  • RouterHub 存在于基础库, 能够被看做是全部组件都须要遵照的通信协议, 里面不只能够放路由地址常量, 还能够放跨组件传递数据时命名的各类 Key 值, 再配以适当注释, 任何组件开发人员不须要事先沟通只要依赖了这个协议, 就知道了各自该怎样协同工做, 既提升了效率又下降了出错风险, 约定的东西天然要比口头上说强
  • Tips: 若是您以为把每一个路由地址都写在基础库的 RouterHub 中, 太麻烦了, 也能够在每一个组件内部创建一个私有 RouterHub, 将不须要跨组件的路由地址放入私有 RouterHub 中管理, 只将须要跨组件的路由地址放入基础库的公有 RouterHub 中管理, 若是您不须要集中管理全部路由地址的话, 这也是比较推荐的一种方式。

7.4.ARouter路由原理:

ARouter维护了一个路由表Warehouse,其中保存着所有的模块跳转关系,ARouter路由跳转实际上仍是调用了startActivity的跳转,使用了原生的Framework机制,只是经过apt注解的形式制造出跳转规则,并人为地拦截跳转和设置跳转条件

相关文章
相关标签/搜索