Android 高级面试-5:四大组件、系统源码等

1、四大组件

1.1 Activity

  • Q:在两个 Activity 之间传递对象还需要注意什么呢?

对象的大小。Intent 中的 Bundle 是使用 Binder 机制进行数据传送的。能使用的 Binder 的缓冲区是有大小限制的(有些手机是 2 M),而一个进程默认有 16 个 Binder 线程,所以一个线程能占用的缓冲区就更小了(有人以前做过测试,大约一个线程可以占用 128 KB)。可以使用 EventBus 来传递数据,而不是直接使用 Intent 进行传递。

  • Q:onSaveInstanceState() 和 onRestoreInstanceState()

当 Activity 被销毁的时候回调用 onSaveInstanceState() 方法来存储当前的状态。这样当 Activity 被重建的时候,可以在 onCreate()onRestoreInstanceState() 中恢复状态。

对于 targetAPI 为 28 及以后的应用,该方法会在 onStop() 方法之后调用,对于之前的设备,这方法会在 onStop() 之前调用,但是无法确定是在 onPause() 之前还是之后调用。

onRestoreInstanceState() 方法用来恢复之前存储的状态,它会在 onStart()onPostCreate() 之间被调用。此外,你也可以直接在 onCreate() 方法中进行恢复,但是基于这个方法调用的时机,如果有特别需求,可以在这个方法中进行处理。

  • Q:SingleTask 启动模式
  • Q:Activity 启动模式
  1. standard:默认,每次启动的时候会创建一个新的实例,并且被创建的实例所在的栈与启动它的 Activity 是同一个栈。比如,A 启动了 B,那么 B 将会与 A 处在同一个栈。假如,我们使用 Application 的 Context 启动一个 Activity 的时候会抛出异常,这是因为新启动的 Activity 不知道自己将会处于哪个栈。可以在启动 Activity 的时候使用 FLAG_ACTIVITY_NEW_TASK。这样新启动的 Acitivyt 将会创建一个新的栈。
  2. singleTop:栈顶复用,如果将要启动的 Activity 已经位于栈顶,那么将会复用栈顶的 Activity,并且会调用它的 onNewIntent()。常见的应用场景是从通知打开 Activity 时。
  3. singleTask:单例,如果启动它的任务栈中存在该 Activity,那么将会复用该 Activity,并且会将栈内的、它之上的所有的 Activity 清理出去,以使得该 Activity 位于栈顶。常见的应用场景是启动页面、购物界面、确认订单界面和付款界面等。
  4. singleInstance:这种启动模式会在启动的时候为其指定一个单独的栈来执行。如果用同样的intent 再次启动这个 Activity,那么这个 Activity 会被调到前台,并且会调用其 onNewIntent() 方法。
  • Q:下拉状态栏是不是影响 Activity 的生命周期,如果在 onStop() 的时候做了网络请求,onResume() 的时候怎么恢复
  • Q:前台切换到后台,然后再回到前台,Activity 生命周期回调方法。弹出 Dialog,生命值周期回调方法。
  • Q:Activity 生命周期
  • Q:Activity 上有 Dialog 的时候按 Home 键时的生命周期
  • Q:横竖屏切换的时候,Activity 各种情况下的生命周期

Android 下拉通知栏不会影响 Activity 的生命周期方法。

弹出 Dialog,生命周期:其实是否弹出 Dialog,并不影响 Activity 的生命周期,所以这时和正常启动时 Activity 的生命回调方法一致: onCreate() -> onStart() -> onResume()

Activity 的生命周期

这里我们总结一下在实际的使用过程中可能会遇到的一些 Acitivity 的生命周期过程:

  1. 当用户打开新的 Activity 或者切换回桌面:会经过的生命周期为 onPause()->onStop()。因为此时 Activity 已经变成不可见了,当然,如果新打开的 Activity 用了透明主题,那么 onStop() 不会被调用,因此原来的 Activity 只是不能交互,但是仍然可见。
  2. 从新的 Activity 回到之前的 Activity 或者从桌面回到之前的 Activity:会经过的生命周期为 onRestart()->onStart()-onResume()。此时是从 onStop() 经 onRestart() 回到 onResume() 状态。
  3. 如果在上述 1 的情况下,进入后台的 Activity 因为内存不足被销毁了,那么当再次回到该 Activity 的时候,生命周期方法将会从 onCreate() 开始执行到 onResume()。
  4. 当用户按下 Back 键时:如果当前 Activity 被销毁,那么经过的生命周期将会是 onPause()->onStop()->onDestroy()

具体地,当存在两个 Activity,分别是 A 和 B 的时候,在各种情况下,它们的生命周期将会经过:

  1. Back 键 Home 键
    1. 当用户点击 A 中按钮来到 B 时,假设 B 全部遮挡住了 A,将依次执行:A.onPause()->B.onCreate()->B.onStart()->B.onResume->A.onStop()
    2. 接1,此时如果点击 Back 键,将依次执行:B.onPause()->A.onRestart()->A.onStart()->A.onResume()->B.onStop()->B.onDestroy()
    3. 接2,此时如果按下 Back 键,系统返回到桌面,并依次执行:A.onPause()->A.onStop()->A.onDestroy()
    4. 接2,此时如果按下 Home 键(非长按),系统返回到桌面,并依次执行A.onPause()->A.onStop()。由此可见,Back 键和 Home 键主要区别在于是否会执行 onDestroy()。
    5. 接2,此时如果长按 Home 键,不同手机可能弹出不同内容,Activity 生命周期未发生变化。
  2. 横竖屏切换时 Activity 的生命周期
    1. 不设置 Activity 的 android:configChanges 时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。
    2. 设置 Activity 的 android:configChanges=“orientation” 时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次。
    3. 设置 Activity 的 android:configChanges=“orientation|keyboardHidden” 时,切屏不会重新调用各个生命周期,只会执行 onConfiguration() 方法。
  • Q:Activity 之间的通信方式
  1. Intent + onActivityResult() + setResult()
  2. 静态变量(跨进程不行)
  3. 全局通信,广播或者 EventBus
  • Q:AlertDialog, PopupWindow, Activity 区别

AlertDialog 是 Dialog 的子类,所以它包含了 Dialog 类的很多属性和方法。是弹出对话框的主要方式,对话框分成支持包的和非支持包的,UI 效果上略有区别。

AlertDialog 与 PopupWindow 之间最本质的差异在于

  1. AlertDialog 是非阻塞式对话框;而PopupWindow 是阻塞式对话框。AlertDialog 弹出时,后台还可以做事情;PopupWindow 弹出时,程序会等待,在PopupWindow 退出前,程序一直等待,只有当我们调用了 dismiss() 方法的后,PopupWindow 退出,程序才会向下执行。我们在写程序的过程中可以根据自己的需要选择使用 Popupwindow 或者是 Dialog.
  2. 两者最根本的区别在于有没有新建一个 window,PopupWindow 没有新建,而是通过 WMS 将 View 加到 DecorView;Dialog 是新建了一个 window (PhoneWindow),相当于走了一遍 Activity 中创建 window 的流程。

Activity 与 Dialog 类似,都会使用 PhoneWindow 来作为 View 的容器。Activity 也可以通过设置主题为 Dialog 的来将其作为对话框来使用。Dialog 也可以通过设置 Theme 来表现得像一个 Activity 一样作为整个页面。但 Activity 具有生命周期,并且它的生命周期归 AMS 管,而 Dialog 不具有生命周期,它归 WMS 管。

  • Q:Activity 与 Service 通信的方式

前提是是否跨进程,如果不跨进程的话,EventBus 和 静态变量都能传递信息,否则需要 IPC 才行:

  1. Binder 用于跨进程的通信方式,AIDL 可以用来进行与远程通信,绑定服务的时候可以拿到远程的 Binder,然后调用它的方法就可以从远程拿数据。那么如果希望对远程的服务进行监听呢?可以使用 AIDL 中的 oneway 来定义回调的接口,然后在方法中传入回调即可。也可以使用 Messenger,向远程发送信息的时候,附带本地的 Messenger,然后远程获取本地的 Messenger 然后向其发送信息即可,详见 IPC 相关一文:《Android 高级面试-2:IPC 相关》
  2. 广播:使用广播实现跨进程通信
  3. 启动服务的时候传入值,使用 startService() 的方式

关于 Activity 相关的内容可以参考笔者的文章:《Android 基础回顾:Activity 基础》

1.2 Service

  • Q:怎么启动 Service
  • Q:Service 的开启方式
  • Q:Service 生命周期

Service的生命周期图
其他,

  1. Service 有绑定模式和非绑定模式,以及这两种模式的混合使用方式。不同的使用方法生命周期方法也不同。
    1. 非绑定模式:当第一次调用 startService() 的时候执行的方法依次为 onCreate()->onStartCommand();当 Service 关闭的时候调用 onDestory()
    2. 绑定模式:第一次 bindService() 的时候,执行的方法为 onCreate()->onBind();解除绑定的时候会执行 onUnbind()->onDestory()
  2. 我们在开发的过程中还必须注意 Service 实例只会有一个,也就是说如果当前要启动的 Service 已经存在了那么就不会再次创建该 Service 当然也不会调用 onCreate() 方法。所以,
    1. 当第一次执行 startService(intent) 的时候,会调用该 Service 中的 onCreate()onStartCommand() 方法。
    2. 当第二次执行 startService(intent) 的时候,只会调用该 Service 中的 onStartCommand() 方法。(因此已经创建了服务,所以不需要再次调用 onCreate() 方法了)。
  3. bindService() 方法的第三个参数是一个标志位,这里传入 BIND_AUTO_CREATE 表示在Activity 和 Service 建立关联后自动创建 Service,这会使得 MyService 中的 onCreate() 方法得到执行,但 onStartCommand() 方法不会执行。所以,在上面的程序中当调用了bindService() 方法的时候,会执行的方法有,Service 的 onCreate() 方法,以及 ServiceConnection 的 onServiceConnected() 方法。
  4. 在 3 中,如果想要停止 Service,需要调用 unbindService() 才行。
  5. 如果我们既调用了 startService(),又调用 bindService() 会怎么样呢?这时不管你是单独调用 stopService() 还是 unbindService(),Service 都不会被销毁,必须要将两个方法都调用 Service 才会被销毁。也就是说,stopService() 只会让 Service 停止,unbindService() 只会让 Service 和 Activity 解除关联,一个 Service 必须要在既没有和任何 Activity 关联又处理停止状态的时候才会被销毁。
  • 进程保活
  • App 中唤醒其他进程的实现方式

1.3 Broadcast

  • Q:BroadcastReceiver,LocalBroadcastReceiver 区别
  • Q:广播的使用场景
  • Q:广播的使用方式,场景
  • Q:广播的分类?
  • Q:广播(动态注册和静态注册区别,有序广播和标准广播)

分类

  1. 按照注册方式:静态注册和动态注册两种:
    1. 静态广播直接在 manifest 中注册。限制:
      1. 在 Android 8.0 的平台上,应用不能对大部分的广播进行静态注册,也就是说,不能在 AndroidManifest 文件对有些广播进行静态注册;
      2. 当程序运行在后台的时候,静态广播中不能启动服务。
    2. 动态广播与静态广播相似,但是不需要在 Manifest
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值