fragment 是一种控制器对象,activity 可以委派它执行任务,这些任务通常是管理用户界面,受管理的用户界面可以是一整屏也可以是整屏的一部分。
现在,Google有两个版本的 fragment 实现可供选择:
原生版本:内置在设备系统中,如果应用要支持各个系统版本,在不同设备上运行的 fragment 可能会有不同的表现,
这主要是因为各个版本的维护有差异,例如某个 bug 在 4.4 系统版本里已修正,而在 4.0 里确没有。
支持库版本:使用类库,应用发布时,会打包在应用里,这样无论在哪个系统版本的设备上运行,都会有相同的表现。
fragment 的支持库版本来自于 AppCompat 库,Google 为开发者提供了很多兼容库,这是其中一个。
添加 fragment 支持库:
要使用 AppCompat 支持库,项目必须将其列入依赖关系:
打开应用模块下的 build.gradle 文件(每个项目都有两个 build.gradle 文件,一个用于整个项目(位于根目录下),一个用于应用模块(位于 app 目录下)):
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
applicationId "com.example.criminalintent"
minSdkVersion 19
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
//表示依赖的 jar 包位于 app/libs 目录下。
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
//添加appcompat支持库,格式使用了 Maven 坐标模式:groupId:artifactId:version
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha7'
testCompile 'junit:junit:4.12'
}
Android Studio在创建项目时,会自动引入一些依赖库,appcompat库一般已经包含在内了。
Gradle允许设置未复制到项目中的依赖项,应用编译时,Gradle会找到并下载指定的依赖包,并将其自动导入到项目中,我们只需要在配置中写好指令,剩下的交个Gradle就好了。
使用Android Studio提供的工具添加支持库:
1. 选择 File -> Project Structure ... 菜单项,打开项目结构对话框
选择左边的应用模块,然后右边选择Dependencies选项(应用模块的依赖项都在这里了):
3. 点击右上角的 + 按钮,选择 Library dependency 界面添加新的依赖项:
搜索选择需要添加的依赖项,点击 OK 就可以了,回到 app/build.gradle 文件,就可以看到选择的依赖已经成功添加到文件中了。
如果手动修改了 app/build.gradle 文件,就需要同步项目和 Gradle 文件以更新修改内容。同步就是要求 Gradle 通过下载或删除依赖项,基于修改重新编译。
选择 Tools -> Android -> Sync Project with Gradle Files 菜单项可以手动执行同步。
托管 fragment 的 activity 必须完成以下两个任务:
1. 在 activity 的布局中为 fragment 的视图安排位置
(1): 在 activity 的布局文件中添加 fragment
这种方式简单但不够灵活,相当于将 fragment 及其视图与 activity 的视图绑定在一起,并且在 activity 的生命周期过程中,无法替换 fragment 视图。
(2): 在 activity 的代码中添加 fragment
这种方式比较复杂,但是可以动态的控制 fragment。
2. 管理相应 fragment 实例的生命周期
fragment的生命周期:
类似于 activity 的生命周期,fragment 也具有停止状态,暂停状态,和运行状态。fragment 中许多方法对应着 activity 的生命周期方法,
这种对应非常重要,因为 fragment 代替 activity 工作,所以它的状态应该反映相应 activity 的状态。
fragment 生命周期与 activity 生命周期的一个关键区别在于,fragment 的生命周期方法由托管的 activity 调用,而不是操作系统。
fragment 的生命周期图解:
1. 运行状态
当一个 fragment 是可见的,并且它所关联的 activity 正处于运行状态时,该 fragment 也处于运行状态。
2. 暂停状态
当一个活动进入暂停状态时(由于另一个未占满屏幕的活动被添加到了栈顶),与它相关联的可见 fragment 就会进入暂停状态。
3. 停止状态
当一个活动进入停止状态时,与它相关联的 fragment 就会进入到停止状态;或者通过调用 Transaction 的 remove()、replace() 方法将 fragment 从活动中移除。
但如果在事务提交之前调用 addToBackStack() 方法,这时的 fragment 也会进入到停止状态。进入停止状态的 fragment 对用户来说是完全不可见的,有可能被系统回收。
4. 销毁状态
fragment 总是依附于 activity 而存在的,因此当 activity 被销毁时,与它相关联的 fragment 就会进入到销毁状态;或者在事务提交之前并没有调用 addToBackStack() 方法将
事务添加到返回栈中,这时的 fragment 也会进入到销毁状态。
Fragment 中的附加方法:
onAttach() : 当 fragment 或 activity 建立关联的时候调用
onCreateView() : 为 fragment 创建视图(加载布局)时调用
onActivityCreated() : 确保与 fragment 关联的 activity 一定已经创建完毕时调用
onDestroyView() : 当与 fragment 关联的视图被移除时调用
onDetach() : 当 fragment 和 activity 解除关联时调用
创建 UI fragment:
创建 UI fragment 的步骤和创建 activity 的步骤相同:
1. 定义用户界面布局文件
2. 创建 fragment 类,并设置其视图为定义的布局
3. 编写代码实例化组件
使用 Android Studio 创建 fragment 类:
1. 选择要创建 fragment 类文件的包,右键单击,选择 New -> Fragment -> Fragment (Blank):
2. 编辑要创建的 Fragment 类文件的名字,然后点击 Finish:
Android Studio 会自动帮我创建好 fragment 类文件,并在 res/layout 目录下自动创建好对应的布局文件。
在 activity 对象中使用 fragment:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_crime); //获取 FragmentManager 对象 FragmentManager fm = getSupportFragmentManager(); /* * 通过 fragment 的视图资源ID,从 FragmentManager 对象中获取指定的 fragment 对象 * * 为什么要获取的 fragment 对象可能已经有了? * 当设备旋转或内存回收时,Android 系统会销毁 fragment 所在的 activity,然后重建。 * activity 被销毁时,它的 FragmentManager 会将 fragment 队列保存下来。这样,当 activity * 重建时,新的 FragmentManager 会首先获取保存的队列,然后重建 fragment 队列,从而回复原来的状态。 * */ Fragment fragment = fm.findFragmentById(R.id.fragment_container); //判断获取的 fragment 对象是否存在 if (fragment == null) { //如果获取的 fragment 对象不存在,则新建对应的 fragment 对象 fragment = new CrimeFragment(); /* * 使用 FragmentManager 对象开启 fragment 事务,通过对应的 fragment 对象的视图资源ID添加 fragment 对象 * * fragment 事务被用来添加,移除,附加,分离或替换 fragment 队列中的 fragment 。 * 这是使用 fragment 动态组装和重新组装用户界面的关键。FragmentManager 管理着 fragment 事务回退栈。 * */ fm.beginTransaction() .add(R.id.fragment_container, fragment) .commit(); //提交事务 } }