当前位置: 首页 > news >正文

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

Context

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

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

  • Application
  • Activity
  • Service

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

context

  • 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 由停止状态变为运行状态的时候调用。

activity_lifecycle

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

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

standard

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

singleTop

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

singleTask

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

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

singleInstance

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() 方法。

Activity 启动流程

scheme 页面跳转协议

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

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

Fragment

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

fragment1

fragment2

Fragment 结合 Activity 使用方式

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

  • 在布局中静态添加 <fragment> 标签,通过 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 解除关联的时候调用

activity_fragment_lifecycle

与 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 内存占用较小,所以适合大量动态页面的场景。

相关文章:

  • MySQL通过命令导出导入数据和表
  • python列表中的深浅copy
  • mysql高可用方案之主从架构(master-slave)
  • 中国HBase技术社区第二届MeetUp ——HBase技术解析及应用实践
  • Centos 7.4 安装 Redis 全过程
  • cocos2d-x引擎库binary版本制作(Windows环境)
  • 解决jsfl 弹出警告
  • 基于HTML5技术的电力3D监控应用(一)
  • zabbix安装源
  • 教你在 OSX 下最简单搭建 Clojure 开发环境的步骤
  • Java命令学习系列(七)——javap
  • 点滴积累【C#】---将Excel数据导入到数据库
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • JS操作DOM的几个属性与方法
  • 201771010101 白玛次仁《面向对象程序设计(Java)》第十一周学习总结
  • 分享的文章《人生如棋》
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • ES6 学习笔记(一)let,const和解构赋值
  • Koa2 之文件上传下载
  • Linux下的乱码问题
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • mysql外键的使用
  • Python3爬取英雄联盟英雄皮肤大图
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • sessionStorage和localStorage
  • SpringBoot几种定时任务的实现方式
  • Vue2.x学习三:事件处理生命周期钩子
  • windows-nginx-https-本地配置
  • 第十八天-企业应用架构模式-基本模式
  • 构建二叉树进行数值数组的去重及优化
  • 前端学习笔记之观察者模式
  • 如何在GitHub上创建个人博客
  • 事件委托的小应用
  • 思否第一天
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • ​configparser --- 配置文件解析器​
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (02)Hive SQL编译成MapReduce任务的过程
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (初研) Sentence-embedding fine-tune notebook
  • (二)Eureka服务搭建,服务注册,服务发现
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • (转)Windows2003安全设置/维护
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • **PHP二维数组遍历时同时赋值
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .Net Redis的秒杀Dome和异步执行
  • .net使用excel的cells对象没有value方法——学习.net的Excel工作表问题
  • ?php echo ?,?php echo Hello world!;?