Android 基础面试题总结

点赞关注,不再迷路,你的支持对我意义重大!

🔥 Hi,我是丑丑。本文 「Android 路线」| 导读 —— 从零到无穷大 已收录,这里有 Android 进阶成长路线笔记 & 博客,欢迎跟着彭丑丑一起成长。(联系方式在 GitHub)


四大组件

说一下 Activity 启动模式

要想真正理解 Activity 启动模式,一定要先理解启动模式背后的 Task 工作模型,这样才能更好地记住每种启动模式的特点,以及为什么需要启动模式这种设计。

当我们点击最近任务键,可以查看最近任务列表并在多个应用之间进行切换。不过,更加准确的说法既不是在多个应用间切换,也不是在多个 Activity 之间切换,而是在多个 Task 之间切换。Task 工作模型主要有以下三个重要特点:

  • 回退栈: 每个 Task 都有回退栈,它按照先进后出的顺序维护 Activity 的顺序,当回退栈清空时,Task 的生命周期就结束了。不过,已经消亡的 Task 依然会保留在最近任务列表中,目的是方便用户 “切回去”,不过此时 “切回去” 不是一般的任务切换,而是重新启动 App(可以观察到执行的是启动 App 的动画,而不是切换任务的动画)。

提示: 最近任务列表里的任务不一定是活着的。

  • Task 栈: Activity 可以叠成栈,Task 也可以叠成栈。不过 Task 叠加适用于前台 Task,当 Task 由前台进入后台,叠加的 Task 会在第一时间被拆开。Task 进入后台的场景有两种:
    • 1、按 Home 键返回桌面;
    • 2、按最近任务键查看最近任务列表。

注意: 查看最近任务列表的时候 Task 就已经进入后台,而不是在切换任务之后才进入后台。

  • taskAffinity(任务相关性): 每个 Activity 都有 taskAffinity,Activity 默认取 Application,而 Application 默认取应用包名,每个 Task 的 taskAffinity 又取自栈底 Activity 的 taskAffinity。既然 Task 的 taskAffinity 取自栈底 Activity,那么说明可能会存在多个 taskAffinity 相同的Task。需要注意:taskAffinity 冲突的 Task 只会在最近任务列表里出现一个。

提示: 最近任务列表里的看不到的任务不一定是消亡的。

理解了 Task 工作模型的三个重要特点,现在我们来讨论不同启动模式的特点。

  • Standard(默认)的行为规则总结起来是 “在启动的 Task 创建”:
    在 Task A 启动 Activity,Activity 会被直接进入到 Task A 的栈顶,在不同的 Task 里打开同一个 Activity,Activity 会被创建多个实例分别放进每一个 Task,互不干扰。这是符合大部分产品逻辑和用户心理的,所以这是默认的设置。当你的产品逻辑和默认规则不同时,你就需要使用其他的启动模式。

  • SingleTask 的行为规则是总结起来是 “在固定的 Task 创建 + 在 Task 内唯一”:

    • 在固定的 Task 创建:在 Task A 启动 Activity,系统会判断 Task A 的 taskAffinity 和新 Activity 的 taskAffinity 是否相同。如果相同,新 Activity 入栈,如果不同,新 Activity 会进入和自己 taskAffinity 相同的 Task(可以观察到执行了任务切换的动画,而不是一般的 Activity 入场动画)。这样就保证了 SingleTask Activity 一定会在固定的 taskAffinity Task 里创建。

    • 在 Task 内唯一:如果要启动的 Acitivity 已经在 Task,那么会直接复用并回调 onNewIntent() 来刷新界面。另外,如果该 Activity 上方叠加了其他 Activity,那么其他 Activity 都会弹出栈。

在 SingleTask 的两条规则限定之下,SingleTask Activity 事实上在全局只有一个单例对象,那么名称为 “单例” 的 SingleInstance 的行为规则是怎样的呢?

  • SingleInstance 的行为规则与 singleTask 基本一致,但增加了更加严格独占性 “Task 里只有这一个 Activity”:
    「Task A」打开「Task B」的 Activity,Activity 不会进入到 Task A 里,而是会创建一个新的 Task,然后随着整个 Task 一起压在 Task A 上面。随后用户继续启动 Activity,新的 Activity 并不会进入同一个 Task 里,而是会在另一个 Task 里创建,然后整个 Task 拿过来压在上面。

提示: 当我们使用 SingleInstance 打开 Activity 时,我们会发现最近任务列表里找不到这个任务,这是因为 taskAffinity 冲突了。

  • SingleTop 的行为规则和 Standard 基本一致,但增加了额外 “栈顶复用” 规则:
    如果 Task 栈顶的 Activity 恰好就是要启动的 Activity,那么系统不会创建新的 Activity,而是会回调 onNewIntent()。

除了四种启动模式,还有其他方式可以影响 Activity 的行为规则:

  • Allow Reparenting 行为规则是 “在启动的 Task 创建 + 迁移”:
    • 在启动的 Task 创建:「Task A」打开「Task B」的 Activity,Activity 会被直接进入到 Task A 的栈顶,这与 Standard 模式类似;
    • 迁移:有两个时机会进行 Activity 迁移:
      1、Task B 启动时;
      2、Task A 进入后台并且 Task B 已经存在,该 Activity 会自动迁移到 Task B 中。

注意: android:allowTaskReparenting 属性 在 Android 9 和 Android 10 系统上是失效的。

启动模式 中文翻译 行为规则
Standard 默认 在启动的 Task 创建
SingleTop 栈顶复用 与 Standard 基本一致,增加 “栈顶复用” 规则
SingleTask 栈内复用 在固定的 Task 创建 + 在 Task 内唯一
SingleInstance 栈内独占 与 SingleTask 基本一致,增加 “栈内独占” 规则
  • 应用场景:

Standard 和 SingleTop 是 Task 内的启动规则,而 SingleTask 和 SingleInstance 是跨 Task 的启动规则(虽然不一定会跨 Task)。因此通常的选择是:用于 在 App 内部交互时使用 Standard 和 SingleTop,在开放给外部共享的 Activity 使用 SingleInstance,而 SingleTask 是内部交互和外部共享都可以用。

在更具体的场景上:SingleTop:推送消息(如果当前页面和推送消息点击跳转的页面相同,那么可以考虑复用这个 Activity);SingleTask:应用主页(因为无论从什么场景进入主页,都应该清空上面的 Activity);SingleInstance:开放给外部共享的页面,例如打电话,写短信等页面。


说一下 Activity 生命周期


说一下 Fragment 生命周期


Intent 和 PendingIntent 的区别?

在创建PendingIntent对象时是跟system_process(系统服务进程,AMS、PMS、WMS都在这个进程)有互动的

因为PendingIntent的相关数据都保存在【系统服务进程】,那么就算创建这个对象的进程已经被kill了,只要这个PendingIntent对象还存在,那它还是能够起到作用的。

PendingIntent 可以理解为延迟执行的 Intent,在某个特定条件下才会执行该 Intent。

Flags 的类型:

FLAG_ONE_SHOT:得到的 PendingIntent 只能使用一次,使用一次后自动调用 cancel 方法解除 PendingIntent 和 Intent 的关联
FLAG_NO_CREATE:当 PendingIntent 不存在时,不进行创建,直接返回 null
FLAG_CANCEL_CURRENT:当 PendingIntent 已存在时,执行 cancel 进行解除,再创建一个新的
FLAG_UPDATE_CURRENT:不存在时就进行创建,创建后每次使用会对数据进行更新
FLAG_IMMUTABLE:创建好 PendingIntent 后就保持一成不变
send 方法:

调用 send 方法时会启动包装的 Intent

cancel 方法:

调用 cancel 方法时会解除 PendingIntent 和被包装 Intent 之间的关联,只有创建该 PengdingIntent 的程序才有权解除


如何判断 App 位于前台还是位于后台,如何监听?

PendingIntent

https://developer.android.google.cn/guide/topics/ui/notifiers/notifications

https://www.youtube.com/watch?v=nRcYhsDTyjo
https://www.youtube.com/watch?v=Bh9qg9NivtU

相关深入文章:


    1. ActivityA -> Activity B -> Activity A
    2. Activity A 启动模式为 singleTask
    3. Activity B 启动模式为常规模式
    4. 问 A 启动 B,B 又启动 A 的生命周期调用顺序?

2、数据存储

Serializable 和 Parcelable 的区别?

我们一定要分清楚什么是协议协议和什么是实现:举个例子,Json 是序列化协议,而 Gson、fastJson、jackJson 这些是对 Json 协议的实现 (序列化目的是将对象转换为可以存储或传输的形式,在将来,反序列化就是把数据重新创建为新的对象。为了保证序列化和反序列化前后的对象信息一致,就需要定义序列化协议,只要你遵循序列化协议,你也可以创建一个新的序列化实现)。现在,我们再回过头来讨论 Serializable([ˈsɪərɪəlaɪzəbl]) 和 Parcelable ([ˈpɑːsləbl]) 的区别:

  • 协议:

先讨论两者的协议:

严格来说,Serializable 只是一个序列化实现,它背后是 JDK 序列化协议(另一个实现有 FST(fast-serialization),它是兼容 JDK 序列化协议的,但效率和产物优于 Serializable)。这种协议的序列化大体上是一种 “TLV(Type-Length-Value)” 编码,也就是说编码中会带有字段类型 / 长度等信息,有效载荷低。而 Parcelable 的编码更紧凑,大体上是通过一个游标指针 nativePtr 来操作序列化数据:序列化写入数据后,游标移动数据长度(超出空间时会扩展),反序列化读取数据,也移动数据长度,有效载荷高(牺牲了扩展性和便利性)。

  • 实现:

再讨论两者的实现细节:

严格来说,虽然两者的目的都是序列化,但是它们的使用场景是不一样的,Serializable 做的事情就是把 JDK 序列化协议实现出来,再对外提供一套 API(ObjectInput/OutputStream),这和 Protobuf / Gson 等做的事情是类似的。而 Parcelable 除了序列化这个目的之外,还是对 Android 进程间数据传输做的针对性优化:通过共享内存(memcpy)作为进程间传输的媒介,Android 中的 IBinder 通信的数据载体,用的就是 Parcelable。

  • Serializable 的其他实现细节:
    • 1、Serializable / Externalizable 只是标记接口,真正的序列化实现在 ObjectInput/OutputStream;
    • 2、序列化产物会带有当前类的 SerialVersionUID 版本,反序列化时会对比类的 SerialVersionUID 版本与序列化数据中的版本是否一致,如果不一致会抛出 InvalidClassException;
    • 3、反序列化使用反射创建对象;
    • 4、网上说 Serializable 序列化过程有文件 I/O,这个说法是不严谨的,应该说序列化本身是没有文件 I/O 的,但要进程间传输序列化数据,可能就需要文件 I/O。如果使用 Parcelable 就通过进程共享内存传输,不需要经过磁盘文件;
    • 5、序列化产物举例:
类定义:
class TestSerial implements Serializable {
    public byte version = 100;
}
------------------------------------------------------------------
序列化产物:
AC ED (序列化协议)
00 05 (序列化版本)
73     (TC_OBJECT. 新的对象)
72     (TC_CLASSDESC. 这是一个新类描述) 
00 0A  (类名的长度)
53 65 72 69 61 6C 54 65 73 74 (类的名称) 
05 52 81 5A AC 66 02 F6 (SerialVersionUID)
02     (Various flags,0x02代表这个对象支持序列化) 
00 01  (类有几个字段) 
49     (代表是int类型)
00 07  (字段名称的长度)
76 65 72 73 69 6F 6E (version, 字段的名称)
78     (TC_ENDBLOCKDATA, 描述的结束符)
70     (TC_NULL)
00 00 00 64 (version的值)
  • Parcelable 的其他实现细节:
    • 1、Parcelable 真正的序列化实现在 native 层 Parcel.cpp
    • 2、write 和 read 的顺序要保持一致;
    • 3、反序列化未使用反射??

相关深入文章:
Parcelable vs Serializable
Parcelable 最强解析
Parcelable 为什么效率高于 Serializable ?


3. 资源

mipmap 和 drawable 的区别?

mipmap 文件夹存放应用启动图标,而其他类型的图片资源(如位图、点 9 图、矢量图)都应该存放在 drawable 文件夹。Launcher(桌面)在显示应用图标时,可以选择显示比当前屏幕更高密度的图片,以获取更高的清晰度和质量。

mipmap 和 drawable 的另一个区别体现在发布应用时的优化差异:在发布应用时,开发者可以向 Google Play 上传 App Bundle,Google Play 会创建优化的 Apk。比如对于 xhdpi 的设备,它会删除所有其他密度的 drawable 文件夹,只保留 xhdpi 的 drawable 文件夹和通用的 drawable 文件夹。因此用户下载的 Apk 包体积更小。mipmap 文件夹不同,优化 Apk 时所有的 mipmap 文件夹都会保留。

https://gitee.com/xcy001/AndroidInterview/blob/master/%E9%9D%A2%E8%AF%95%E9%A2%98%E6%80%BB%E7%BB%93%EF%BC%88Android%E9%83%A8%E5%88%86%EF%BC%89.md

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容