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

2019最新Android中级面试题目汇总解答,第1张

概述注:因为实际开发与参考答案会有所不同,再者怕误导大家,所以这些面试题答案还是自己去理解!面试官会针对简历中提到的知识点由浅入深提问,所以不要背答案,多理解。Android进阶延伸点1、如何进行单元测试,如何保证App稳定?参考回答:要测试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的大小如何压缩 ?

参考回答:

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,和mipsresources.arsc:包含已编译的资源。该文件包含res/values/ 文件夹所有配置中的XML内容。打包工具提取此XML内容,将其编译为二进制格式,并将内容归档。此内容包括语言字符串和样式,以及直接包含在*resources.arsc8文件中的内容路径 ,例如布局文件和图像。classes.dex:包含以Dalvik / ART虚拟机可理解的DEX文件格式编译的类。AndroIDManifest.xml:包含核心AndroID清单文件。该文件列出应用程序的名称,版本,访问权限和引用的库文件。该文件使用AndroID的二进制XML格式。

lib、class.dex和res占用了超过90%的空间,所以这三块是优化Apk大小的重点(实际情况不唯一)3.2.减少res,压缩图文文件

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

3.3.减少dex文件大小

添加资源混淆



shrinkResources为true表示移除未引用资源,和代码压缩协同工作。MinifyEnabled为true表示通过ProGuard启用代码压缩,配合proguardfiles的配置对代码进行混淆并移除未使用的代码。代码混淆在压缩apk的同时,也提升了安全性。3.4.减少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.插件化原理分析

参考回答:

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

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

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

类加载机制
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,遇到某些特殊情况甚至可以升级或者降级

举个简单的模型例子

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注解的形式制造出跳转规则,并人为地拦截跳转和设置跳转条件

常见的组件化方案如下

AndroID中级面试题目汇总解答到此就结束了想获取更多AndroID方面的技术知识或者面试资料的可以查看我主页

@H_399_301@

总结

以上是内存溢出为你收集整理的2019最新Android中级面试题目汇总解答全部内容,希望文章能够帮你解决2019最新Android中级面试题目汇总解答所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1111873.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存