Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment

Context

Android 系统组件不同于普通类对象,能够直接创建实例,需要各自的上下文环境——Context。
Context 上下文环境确保 Android 系统组件(Activity、Service、BroadcastReceiver)能够正常工作。

Context 大致分为三种类型(通常可以通用):

  • Application
  • Activity
  • Service

getApplication() = getApplicationContext() = Application
getApplicationContext() 方法的作用域更广,任何一个 Context 实例(Activity, Service)通过调用 getApplicationContext() 方法都可以获取到 Application。

Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment_第1张图片

  • ContextWrapper 抽象接口类
  • ContextImpl 具体实现类

ContextWrapper 中的方法通过组合委托方式交由 ContextImpl 具体实现。
getBaseContext() = ContextImpl

Context 数量计算公式:
Context 数量 = Activity 数量 + Service 数量 + 1(Application)

Activity

Activity 返回栈

Android 使用任务(Task)返回栈(Back Stack)管理 Activity,任务是一组存放在栈(后进先出)里的 Activity 集合。

返回栈管理 Activity 的入栈出栈操作,例如:启动新的 Activity 执行入栈操作;Back 键返回或调用 finish() 方法,销毁 Activity 执行出栈操作。

系统总是显示处于栈顶的 Activity。

任务(Task)从前台移至后台时,返回栈中所有的 Activity 都会进入停止状态,但是各个 Activity 在栈中的顺序都会原封不动保留。

Activity 四种状态

  • 运行状态
  • 暂停状态
  • 停止状态
  • 销毁状态

运行状态

Activity 处于返回栈的栈顶位置,正在运行与用户发生着交互,系统不愿回收此种状态的 Activity。

暂停状态

Activity 不再处于返回栈的栈顶位置,但是依然可见,并非每个 Activity 都会占满屏幕,例如对话框形式的 Activity 只是占据部分区域,其后面的 Activity 是可见的。系统同样不愿回收此种状态的 Activity,除非在内存严重不足的情况下,才考虑回收此种状态的 Activity。

停止状态

Activity 不再处于返回栈的栈顶位置,并且完全处于不可见状态,系统仍然会保存停止状态的 Activity 的成员变量,但并不可靠,当其他地方需要内存时,系统可能回收此种状态的 Activity,保证内存充足。

销毁状态

Activity 从返回栈出栈变为销毁状态,系统乐于回收此种状态的 Activity,保证内存充足。

Activity 生命周期回调方法

  • onCreate()
  • onStart()
  • onResume()
  • onPause()
  • onStop()
  • onDestroy()
  • onRestart()

onCreate() 方法在 Activity 第一次被创建的时候调用,完成 Activity 初始化操作,例如加载布局、绑定事件...。
onStart() 方法在 Activity 由不可见变为可见的时候调用。
onResume() 方法在 Activity 准备好与用户进行交互的时候调用。
onPause() 方法在系统准备启动或者恢复另一个 Activity 的时候调用。
onStop() 方法在 Activity 由可见变为不可见的时候调用。
onDestroy() 方法在 Activity 销毁之前调用。
onRestart() 方法在 Activity 由停止状态变为运行状态的时候调用。

Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment_第2张图片

onPause() ——> onResume() 暂停状态向运行状态切换。对话框式 Activity 无法占满屏幕,其后面的 Activity 依然可见。

Activity 回收情况

Activity 执行 onStop() 方法,处于停止状态(不可见),可能被系统回收。
若系统内存充足,保留 Activity 状态数据,当用户再次返回 Activity,执行 onRestart() 方法。
若系统内存不足,将 Activity 回收,用户再次返回 Activity,执行 onCreate() 而非 onRestart()。

Activity 提供 onSaveInstanceState() 回调方法,保证在 Activity 被回收之前调用此方法,保存临时数据。随后可以在 Activity onCreate(Bundle savedInstanceState) 方法恢复数据。

  • 完整生存期:onCreate() ——> onDestroy()
  • 可见生存期:onStart() ——> onStop()
  • 前台生存期:onResume() ——> onPause()

Activity 启动模式

定义启动模式

  1. 使用 AndroidManifest.xml 文件指定 标签的 android:launchMode 属性。
  2. 调用 startActivity() 方法时使用 Intent FLAG 参数。
    Intent 中定义的启动模式 FLAG 将会覆盖 AndroidManifest.xml 文件中的定义。
  • standard
  • singleTop
  • singleTask
  • singleInstance

standard 模式不在乎一个 Activity 是否已经存在于返回栈之中,每次启动都会创建新的 Activity 放入返回栈中。

Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment_第3张图片

singleTop 模式启动 Activity 时,如果当前返回栈的栈顶位置已是该类型 Activity,则无需创建新的实例,直接使用栈顶位置的 Activity。如果该类型 Activity 存在于返回栈中,但并非处于栈顶位置,还是会创建新的 Activity 实例。

Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment_第4张图片

singleTask 模式启动 Activity 时,如果当前返回栈中存在该类型 Activity,则直接使用该 Activity 实例,并将这个 Activity 实例之上的 Activity 统统出栈。如果整个返回栈中不存在该类型 Activity,还是会创建新的 Activity 实例。

Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment_第5张图片

singleTop 和 singleTask 都是为了解决重复创建 Activity 问题,singleTop 的作用域是栈顶,singleTask 的作用域是整个返回栈。

singleInstance 创建活动到独立返回栈,从而实现不同程序可以共享 Activity 实例。

Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment_第6张图片

taskAffinity 参数用于指定 Activity 依附于哪个任务。

Activity 启动流程

ActivityManagerService,负责系统中所有的 Activity 的生命周期。
ActivityThread,App 真正的入口,执行 main() 方法,初始化主线程的消息循环队列。
Zygote,Linux 系统所有进程均是由 “init“ 进程拷贝(fork)而来。

点击应用图标 Launcher 程序将点击事件转换为 startActivity(intent),通过 Binder IPC 路由通知 ActivityManagerService。ActivityManagerService 首先通过 PackageManager 收集 intent 信息,然后检查是否具有唤醒组件的权限,开启新的 TASK(FLAG_ACTIVITY_NEW_TASK),最后创建进程去实例化组件。

创建进程过程:
ActivityManagerService Process.start() 由 Zygote 进程(Linux init 进程)孵化出应用进程,并实例化 ActivityThread(主线程/UI 线程)对象执行 main() 方法,初始化主线程的 Looper、Handler,开启消息循环队列,无限等待消息到来(Looper.loop())。

绑定应用过程:
bindApplication() 方法发送 BIND_APPLICATION 消息到消息循环队列,关联(attach)创建的进程和应用程序。加载应用程序 Class 到线程私有内存空间。

启动 Activity 过程:
realStartActivity() 发送 LAUNCH_ACTIVITY 消息到消息循环队列,启动 Activity 管理自身生命周期,首先回调 onCreate() 方法。

Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment_第7张图片

scheme 页面跳转协议

自定义 scheme 协议以便跳转至 App 期望到达的各个页面,可由服务端定制化。

  • 原生 App 页面
  • HTML5 页面
  • 其他 App 页面

Fragment

Fragment 是一种可以嵌入在 Activity 中的 UI 片段,就好像是 mini Activity 同样包含布局,并拥有自己的生命周期。Android 引入 Fragment 概念,力求在开发过程中同时兼顾手机和平板屏幕的大小。

Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment_第8张图片

Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment_第9张图片

Fragment 结合 Activity 使用方式

静态创建方式和动态创建方式

  • 在布局中静态添加 标签,通过 android:name 属性指定 Fragment 类名。
  • 在程序运行时动态地添加 Fragment 到 Activity 中。

动态添加过程:

  1. 创建 Fragment 实例
  2. 获取 FragmentManager,在 Activity 中通过 getSupportFragmentManager() 方法可以得到。
  3. FragmentManager 开启事务 FragmentTransaction
  4. FragmentTransaction 向布局中的指定容器(ViewGroup)添加或替换(replace) Fragment
  5. 提交事务 FragmentTransaction.commit()

FragmentTransaction add()、replace() 方法区别

不同之处在于,是否清空容器后再添加 Fragment,replace() 会清空而 add() 不会。通常 add() 方法需要配合 hide()remove() 方法一起使用,而 replace() 方法一般单独使用。

transaction.replace(viewId, fragment);

等价操作:

transaction.add(viewId, fragment);
transaction.show(fragment);
transaction.hide(preFragment);
transaction.remove(preFragment);

Fragment 通信方式

Activity 调用 Fragment 方法:Activity FragmentManager findFragmentById() 方法获取 Fragment 实例。

Fragment 调用 Activity 方法:Fragment getActivity() 方法获取 Activity 实例。

Fragment 调用 Fragment 方法:Activity 作为中介。

Fragment 返回栈

FragmentTransaction 提供 addToBackStack() 方法,可以添加事务到返回栈中。根据应用需求决定是否使用 addToBackStack() 方法。例如 Back 键返回时显示上一次 FragmentTransaction 记录结果,则需事先调用 addToBackStack() 方法。

addToBackStack() 方法保存的是一系列针对 FragmentTransaction 的操作记录。

Fragment 四种状态

  • 运行状态
  • 暂停状态
  • 停止状态
  • 销毁状态

运行状态:Fragment 所关联的 Activity 处于运行状态

暂停状态:Fragment 所关联的 Activity 处于暂停状态

停止动态:当 Activity 进入停止状态时,与它相关联的 Fragment 就会进入停止状态。或者通过调用 FragmentTransaction 的 remove()replace() 方法将 Fragment 从 Activity 中移除,但在事务提交之前调用 addToBackStack() 方法,这时 Fragment 也会进入停止状态。

销毁状态:Fragment 依附于 Activity 而存在,因此 Activity 销毁,与它相关联的 Fragment 就会进入销毁状态。或者通过调用 FragmentTransaction 的 remove()replace() 方法将 Fragment 从 Activity 中移除,但在事务提交之前没有调用 addToBackStack() 方法,这时 Fragment 也会进入销毁状态。

Fragment 生命周期回调方法

  • onAttach()
  • onCreate()
  • onCreateView()
  • onActivityCreated()
  • onStart()
  • onResume()
  • onPause()
  • onStop()
  • onDestroyView()
  • onDestroy()
  • onDetach()
  • onRestart()

除了与 Activity 相同的生命周期回调方法之外,Fragment 还附加几个回调方法。

onAttach():当 Fragment 和 Activity 建立关联的时候调用
onCreateView():为 Fragment 创建视图(加载布局)的时候调用
onActivityCreated():确保 Fragment 和关联的 Activity 都创建完毕
onDestroyView():当 Fragment 移除视图结构的时候调用
onDetach():当 Fragment 和 Activity 解除关联的时候调用

Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment_第10张图片

与 Activity 生命周期协调一致

Fragment 与 ViewPager 组合使用

ViewPager extends ViewGroup,允许用户左右滑动(幻灯片效果)浏览视图,并根据提供的 PagerAdapter 填充数据。

FragmentPagerAdapter 与 FragmentStatePagerAdapter 的区别

ViewPager 提供两种页面适配器(PagerAdapter)来管理不同的 Fragment 之间滑动切换。

FragmentPagerAdapter:ViewPager 中的所有 Fragment 实例常驻内存,当 Fragment 变得不可见时仅销毁视图结构,即调用 onDestroyView() 方法。由于 FragmentPagerAdapter 内存消耗较大,所以适合少量静态页面的场景。

FragmentStatePagerAdapter:当 Fragment 变得不可见时,不仅销毁视图层次,Fragment 实例也被销毁,即调用了 onDestroyView()onDestroy() 方法,仅保存 Fragment 状态。相比而言, FragmentStatePagerAdapter 内存占用较小,所以适合大量动态页面的场景。

你可能感兴趣的:(android,java,fragment,activity)