Android 技术重温系列 ( 2 )
来源:互联网 发布:独战乾坤进阶数据大全 编辑:程序博客网 时间:2024/05/24 00:54
Android技术重温系列(2)- Activity
本章节具体回顾一下 Activity 基础知识以及延伸的一点内容。篇幅较长,内容基础,主要是为了重温一下官方提供的 Android 技术。由于篇幅限制,一些案例代码不会全部展示。对此,全部代码会提交到 github 仓库中,可能代码质量不高,但也欢迎大家提出疑问以及文章内的错误,避免误导大家。
Activity
Activity 是 Android 应用的重要组成单元之一(另外三个是 Service、BroadcastReceiver、ContentProvider),用户可与其提供的屏幕进行交互,以执行拨打电话、拍摄照片、发送电子邮件或查看地图等操作。每一个 Activity 都会获得一个用于绘制其用户界面的窗口。
一个应用通常是由多个 Activity 组成的。应用启动后呈现给用户的第一个 Activity 即为主 Activity。每次启动新的 Activity 时,前一个 Activity 便会停止,但系统会在堆栈中保留该 Activity,当新的 Activity 启动时,系统会将其推送到堆栈上,并取得用户焦点。
当一个 Activity 因某个新 Activity 启动而停止时,系统会通过该 Activity 的生命周期回调方法通知其这一状态变化。Activity 因状态变化而收到回调方法可能有若干种,每一种回调都会为您提供执行与该状态变化相对应的特定操作的机会。例如,停止时,Activity 应释放任何大型对象,例如网络对象数据库连接等。当 Activity 恢复时,重新获取所需资源,并恢复执行中断的操作。
Activity 的创建到结束
activity现有子类
建立自己的 Activity 也需要继承 Activity 基类。当然在不同场景下,我们也可以继承 Activity 的子类。我们需要在子类中实现 Activity 在其生命周期的各种状态之间转变时系统调用的回调方法。两个最重要的回调方法是:
- onCreate()
必须实现此方法,系统会在创建 Activity 的时候调用此方法。我们应该在这实现初始化 Activity 的一些操作。最重要的是,必须在此方法内调用 setContentView(),以定义 Activity 的界面布局。
- onPause()
系统将此方法作为用户离开 Activity 的第一个信号 ( 并不意味着 Activity 会被销毁 ) 进行调用。我们通常应该在此方法中确认当前用户会话结束后仍然有效的任何更改。
activity 在 androidManifast.xml 中的配置
Android 应用要求所有的应用程序组件 ( Activity、Service、BroadcastReceiver、ContentProvider ) 都必须显示进行配置。
<manifest ... > <application ... > <activity android:name=".ExampleActivity" android:icon="@mipmap/small_pic" android:lable="@string/lable" android:exported="true" android:launchMode="singleInstance"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LANUCHER"/> </intent-filter> </activity> ... </application ... > ...</manifest >
从上面的配置来看,配置 Activity 时通常指定如下几个属性:
- name:指定该 Activity 的实现类的名字。
- icon:指定该 Activity 对应的图标。
- lable:指定该 Activity 的标签。
- exported:指定该 Activity 是否允许被其他应用调用。
- launchMode:指定该 Activity 的加载模式。
intent-filter中的属性会在文章之后的文章内在做解释。
activity 启动和关闭
Android 启动其他 Activity 有如下两个方法:
- startActivity(Intent intent):启动其他 Activity。
- startActivityForResult(Intent intent, int requestCode):以指定的请求码启动 Activity ,而且程序将会获取新启动的 Activity 返回的结果 ( 通过重写 onActivityResult(…) 方法来获取 )。
Android 为关闭 Activity 准备了如下两个方法:
- finish():结束当前的 Activity。
- finishActivity(int requestCode):结束以 startActivityForResult(Intent intent, int requestCode) 方法启动的 Activity。
使用 Bundler 在 Activity 之间交换数据
当一个 Activity 启动另一个 Activity 时,常常会有一些数据需要传递。对于 Activity 而言,通过 Intent 可以让 Activity 之间进行数据交换更简单。
Intent 提供了多个重载的方法来携带额外的数据。如下所示:
- putExtras(Bundle data):向 Intent 中放入需要 “携带” 的数据包。
- Bundle getExtras():取出 Intent 中所有 “携带” 的数据包。
- putExtras(String name, Xxx value):向 Intent 中按 key-value 对的形式存入数据。
- getXxxExtra(String name):从 Intent 中按 key 取出指定类型的数据。
上面方法中的 Bundle 就是一个简单的数据携带包,该 Bundle 对象包含了多个方法来存入数据:
- putXxx(String name, Xxx value):向 Bundle 中放入键值对数据。
- putSerializable(String key, Serializable data):向 Bundle 中放入一个可序列化的对象。
- getXxx(String name):从 Bundle 中取出数据。
- getSerializable(String key):从 Bundle 中取出可序列化对象。
当程序调用 Intent 的 putExtras(String name,Xxx value) 方法向 Intent 中存入数据时,如果该 Intent 中已经有了 Bundle 对象,则该方法直接向 Intent 所携带的 Bundle 中存入数据;如果 Intent 还没有 Bundle 对象, 则该方法会先为 Intent 创建一个 Bundle,再向 Bundle 中存入数据。
Activity 生命周期与加载模式
Activity 图解
按照生命周期来说,Activity 大致会经过如下 4 种生命状态:
- 运行状态:此 Activity 位于屏幕前台并具有用户焦点。
- 暂定状态:其他 Activity 位于屏幕前台,此 Activity 可见,没有焦点。
- 停止状态:此 Activity 不可见,没有焦点。
- 销毁状态:此 Activity 结束,或者系统回收进程结束。
通过观察上图,整个 Activity 生命周期所经历的回调函数又可以进行区间归类:
- 有效的生命周期:发生在 onCreate() 后与 onDestory() 前。
- 可见的生命周期:发生在 onStart() 后与 onStop() 前。
- 前台的生命周期:发生在 onResume() 后与 onPause() 前。
Activity 生命周期回调方法汇总表
名为 “ 是否能时候终止 ” 的列表项表示系统能否在不执行另一个 Activity 代码的情况下,在方法返回后随时承载 Activity 的进程。
协调 Activity
生命周期回调的顺序进过明确定义,当两个 Activity 位于同一进程,并且由一个 Activity 启动另一个 Activity 时,其定义尤其明确。以下是当 ActivityA 启动 ActivityB 时一系列操作的发生顺序:
1. ActivityA 的 onPause() 方法执行。
2. ActivityB 的 onCreate()、onStart() 和 onResume() 方法依次执行。
3. 然后,ActivityA 在屏幕上不可见,则其 onStop() 方法执行。
Activity 的加载模式
在清单文件中声明 Activity 时,可以使用 元素的 lanuchMode 属性指定 Activity 该如何与 Task 关联。 launchMode 属性指定有关应用如何将 Activity 启动到任务中的指令。可以分配给 lanuchMode 属性的启动模式共有 4 种:
- “ standard ”:默认模式,系统在启动 Activity 的任务中创建 Activity 的实例并向其传送 Intent。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例对象。
- “ singleTop ”:基本与 standatd 模式类似,不同一点在于,如果 Activity 已经位于任务的顶部时,系统会通过调用该实例的 onNewInente() 方法向其传送 Intent ,而不是创建 Activity 的新实例。
- “ singleTask ”:系统创建新的实例并位于新任务的顶部的 Activity。但是,如果该 Activity 的一个实例已存在与一个单独的任务中,则系统会通过调用现有实例的 onNewInente() 方法向其传送 Intent,而不是创建新实例。一次只能存在 Activity 的一个实例。
- “ singleInstance ”:与 singleTask 模式类似,只是系统不会将任何其他 Activity 启动到包含实例的任务中。该 Activity 始终只有是其任务唯一仅有的成员;由此 Activity 启动的任何 Activity 均在单独的任务中打开。
Fragment
Fragment 基础与特征
Fragment 表示 Activity 中行为或用户界面部分。我们可以将多个片段组合成一个 Activity 中来构建多窗口 UI,以及在多个 Activity 中重复使用某个片段。我们可将片段视为 Activity 的模块化组成部分,它具有自己的生命周期,能接收自己的输入事件,并且可以在 Activity 运行时添加或移除片段。关于片段,可以归纳如下几个特征:
- Fragment 总是作为 Activity 界面的组成部分。Fragment 可以调用 getActivity() 方法获取它所在的 Activity,Activity 可调用 FragmentManager 的 findFragmentById() 或 findFragemntByTag() 方法来获取 Fragment。
- 在 Activity 运行的过程中,可调用 FragmentManager 的 add()、remove()、replace() 方法动态的添加、删除或替换 Fragment。
- 一个 Activity 可以同时组合多个 Fragment;反过来,一个 Fragment 也可以被多个 Activity 复用。
- Fragment 可以响应自己的输入事件,并拥有自己的生命周期,但它们的生命周期直接被其所属的 Activity 的生命周期所控制。
创建 Fragment
创建 Fragment 需要创建 Fragment 或者其子类。Fragment 创建的代码与 Activity 非常相似。包含与 Activity 类似的回调方法,如 onCreate()、onStart() 和 onStop()。通常创建 Fragment,我们至少实现以下的生命周期方法:
- onCreate():系统会在创建片段的时候调用此方法。
- onCrreateView():系统会在片段首次绘制在用户界面时调用此方法。
- onPause():系统将此方法作为用户离开片段的第一个信号进行调用。
常见的 Fragment 子类有:
- DialogFragment:显示浮动的对话框。使用此类创建对话框可有效的替代使用 Activity 类中的对话框,因为我们可以将片段对话框纳入由 Activity 管理的片段堆栈中,从而使用户能够返回清除的片段。
- ListFragment:显示由适配器管理的一系列项目,类似与 ListActivity。
- PrefrenceFragment:以列表形式显示 Prefrence 对象的层次结构,类似于 PrefrenceActivity。
通常,片段向宿主 Activity 贡献一部分 UI,作为 Activity 总体视图层次结构的一部分嵌入到 Activity 中。可以通过如下两种方式向 Activity 布局添加片段:
1. 在 Activity 的布局文件中声明片段
这种方式,是将片段当做视图来为其指定布局属性。例如,以下是一个具有两个 Fragment 的 Activity 的布局文件:
“`java
Fragment 管理和 Fragment 事务
想要管理 Activity 中的 Fragment ,需要使用 FragmentManager。可以通过调用 Activity 的 getFragmentManager()。可以使用 FragmentManager 执行的操作包括如下:
- 通过 findFragmentById() 或 findFragmentByTag() 获取 Activity 中存在的 Fragment。
- 通过 popBackStack() 将 Fragment 从堆栈中弹出。
- 通过 addOnBackStackChangeLinstener() 注册一个监听堆栈变化的监听器。
如果需要添加、删除或替换 Fragment,则需要借助于 FragmentTransaction 对象。FragmentTransaction 代表 Activity 对 Fragment 执行的多个改变。
对于每个 FragmentTransaction ,我们都可以在提交前调用 setTransaction() 来设置过度动画
Fragment 生命周期
与 Activity 类似,Fragment 也可归类如下状态:
- 运行状态:此 Fragment 位于前台,拥有用户焦点。
- 暂定状态:其他 Activity 位于前台,但此 Fragment 可见,没有用户焦点。
- 停止状态:此 Fragment 不可见,失去焦点。
- 销毁状态:此 Fragment 被完全删除,或该 Fragment 所在的 Activity 被结束。
Fragment 自身生命周期图
Activity 与 Fragment 生命周期的协调
Fragment 所在的 Activity 的生命周期会直接影响到 Fragment 的生命周期,其表现为,Activity 的每次生命周期回调都会引发每个 Fragment 的类似的回调。不过,Fragment 还有几个额外的生命周期回调,用于处理与 Activity 的唯一交互,以执行构建和销毁 Fragment UI 等操作,这些额外的回调方法是:
- onAttach():在 Fragment 与 Activity 关联时调用。
- onCreateView():调用此方法创建与 Fragment 关联的视图层次结构。
- onActivityCreated():在 Activity 的 onCreate() 方法返回时调用。
- onDestoryView():在移除与 Fragment 关联视图层次结构时调用。
- onDetch():在取消 Fragment 与 Activity 的关联时调用。
Loader
Android 3.0 中引入了加载器,支持轻松在 Activity 或片段中异步加载数据。 加载器具有以下特征:
- 可用于每个 Activity 和 Fragment。
- 支持异步加载数据。
- 监控其数据源并在内容变化时传递新结果。
- 在某一配置更改后重建加载器时,会自动重新连接上一个加载器的游标。 因此,它们无需重新查询其数据
对于文章内没有详细讲到的技术点,今后会单独分享的,本章主要内容还是方便大家回顾一下以前的知识。
参考资料
1. https://developer.android.google.cn/guide/components/activities.html
2. https://developer.android.google.cn/guide/components/fragments.html
3. https://developer.android.google.cn/guide/components/loaders.html
4. https://developer.android.google.cn/guide/components/tasks-and-back-stack.html
5. 《疯狂 Android 讲义》
- Android 技术重温系列 ( 2 )
- Android 技术重温系列 ( 3 )
- Android 技术重温系列 ( 4 )
- Android 技术重温系列 ( 5 )
- Android 技术重温系列 ( 6 )
- Android 技术重温系列 (9)- 布局
- Android 技术重温系列 (12)- Menu
- Android 技术重温系列 (14)- 动画
- Android 技术重温系列 (17)- DataBinding
- Android 技术重温系列 (7)- Android 应用资源_2
- Android 技术重温系列 (8)- AndroidManifest.xml
- Android 技术重温系列 (10)- UI 组件
- Android 技术重温系列 (11)- 对话框的变化
- Android 技术重温系列 (13)- Style 和 Theme
- Android 技术重温系列 (15)- Canvas & Drawables
- Android 技术重温系列 (16)- 数据存储
- Android重温
- 【技术重温】引言
- 鸟哥的Linux私房菜笔记二
- A和B之间的加密通信与HTTPS通信机制
- C# Winform 跨线程更新UI控件常用方法总结(转)
- QString转换为char*需要注意的问题
- uploadfy详解
- Android 技术重温系列 ( 2 )
- [js代码] input checkbox 全选与取消全选
- NodeJS开发调试
- 严重不安全:STL map 使用map[key]==0判断key是否存在于map中
- MyBatis-generator 代码生成工具
- Vuex原来可以这样上手
- hosts
- 同步日志、时间的练习
- MVC