Fragment简单使用
Fragment概述
Fragment是一种可以嵌入到Activity中的UI片段,能够让程序更加合理和充分地利用大屏幕的空间,出现的初衷是为了适应大屏幕的平板电脑,可以将其称为一个小型Activity,又称作Ativity片段。
使用Fragment可以把屏幕划分为几块,然后进行分组,进行模块化管理。Fragment不能单独使用,必须由Activity或另一个Fragment托管。
例如,一个响应各种屏幕尺寸的应用程序。在大屏幕上,采用一个静态抽屉式导航栏和一个网格布局的列表。在小屏幕上,采用一个底部导航栏和一个线性布局的列表。在Activity中管理所有这些变化因素会很复杂。将导航元和内容分离,更易于管理。Activity负责显示正确的导航界面,而Fragment采用适当的布局显示列表。如下图:

Fragment的特点:
- Fragment不能独立存在,必须由Activity或另一个Fragment托管
- 一个Activity里可以有多个Fragment
- 一个Fragment可以被多个Activity重用
- Fragment定义和管理自己的布局,有自己的生命周期,并能处理自己的输入事件
- 能在Activity运行时动态地添加或删除Fragment
- 应该只为Fragment提供管理它自己的界面所需的逻辑,应避免让一个Fragment依赖于另一个Fragment或从一个Fragment操控另一个Fragment
Fragment的优势:
- 模块化:我们不必把所有代码全部写在Activity中,而是把代码写在各自的Fragment中
- 可重用:多个Activity可以重复使用一个Fragment
- 可适配:根据硬件的屏幕尺寸、屏幕方向,能够方便地实现不同的布局,用户拥有更好的使用体验。
Fragment生命周期

Fragment的生命周期以及状态之间的转换:

fragment生命周期解析:
|
onAttach() |
当fragment被添加到activity时调用,只调用一次。 这是fragment和activity还没有完全初始化。通常,在该方法中获取到activity的引用,在fragment将来的初始化工作中被使用。 |
|
onCreate() |
创建fragment时调用,只调用一次。在这里可以实例化一些必要的变量、组件,主要是当fragment被暂停 停止时想要保持的数据,以便被恢复。 如果我们要为fragment启动一个后台线程,可以考虑将代码放于此处。 Bundle savedInstance,用于保存Fragment参数, Fragment也可以重写onSaveInstanceState(Bundle outState)方法,保存fragment状态 |
|
onCreateView() |
每次创建、绘制fragment的View时,调用。要返回一个代表fragment根布局的View组件,如果该fragment不提供用户界面,直接返回null。 当系统用到fragment的时候,fragment就要返回它的view,越快越好。 所以尽量在不要在这里做耗时操作,比如从数据库加载大量数据显示listView,当然线程还是可以的。 给当前的fragment绘制ui布局,可以使用线程更新ui。 |
|
onActivityCreated() |
当fragment所在的activity被启动完成时调用,也就是Activity中的onCreate方法执行完后调用。所以与Activity中UI交互操作可以在onActivityCreated()里面进行。 这个方法主要是初始化那些需要父Activity或者Fragment的UI已经被完整初始化才能初始化的元素。 |
|
onStart() |
fragment可见时调用该方法 |
|
onResume() |
fragment可交互时调用该方法 |
|
onPause() |
fragment转到后台或者被删除/替换 时调用该方法。 |
|
onStop() |
fragment将要被停止时调用。 可能的情况:activity被stopped了 或者 fragment被移除但被加入到回退栈中。 一个stopped的fragment仍然时活着的如果长时间不要也会被移除 |
|
onDestroyView() |
销毁fragment中的view时调用。表示fragment销毁相关联的UI布局清除所以跟视图相关的资源 |
|
onDestroy() |
销毁fragment对象,跟activity类似 |
|
onDetach() |
fragment和activity解除关联的时候调用,只调用一次。 |
Fragment基本使用
配置环境
Fragment依赖于AndroidX Fragment库,因此需要将Google Maven存储库添加到project build.gradle文件,以便包含这个依赖项。
buildscript {
...
repositories {
google()
...
}
}
allprojects {
repositories {
google()
...
}
}
为了将AndroidX Fragment库包含在项目中,接着在app的build.gradle文中添加以下依赖项:
dependencies {
val fragment_version = "1.3.6"
// Java
implementation("androidx.fragment:fragment:$fragment_version")
// Kotlin
implementation("androidx.fragment:fragment-ktx:$fragment_version")
}
创建Fragment类
自定义Fragment类,继承自Fragment类或其子类
class ExampleFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_example, container, false)
}
}
定义Fragment的XML布局文件:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ExampleFragment">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_blank_fragment"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
将Fragment添加到Activity中
有静态和动态两种方式添加fragment,这两种方式都需要在Activity的布局文件中添加FragmentContainerView,它是fragment的容器。
静态加载Fragment
直接在activity_main.xml文件中声明添加fragment,给FragmentContainerView的android:name属性指定要实例化的Fragment的类名。当activity的layout被加载之后,指定的fragment会被实例化。代码如下:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.legalsoft.myfirstapp.ExampleFragment"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt的代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
动态加载Fragment
通过编程的方式在MainActivity中添加fragment。仍然需要在activity_main.xml文件中使用FragmentContainerView充当Fragment的容器,和静态加载不同,这里不指定android:name的值,所以不会自动实例化fragment。而是使用FragmentTransaction实例化fragment并将其添加到activity。
activity_main.xml:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if(savedInstanceState == null){
supportFragmentManager.commit {
setReorderingAllowed(true)
add<ExampleFragment>(R.id.fragment_container_view)
}
}
}
}
上例中,只有当savedInstanceState为null时才创建fragment transaction。这能够确保fragment只有在activity第一次创建的时候才会被添加,确保之添加一次。当配置更改(比如横竖屏变化、多窗口模式等)activity重新创建时,savedInstanceState不再为null,fragment不需要第二次被添加,因为fragment会自动从savedInstanceState中恢复。
如果fragment需要一些初始数据,可以通过调用FragmentTransaction.add(),将参数通过 Bundle传递到fragment,如下所示:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if(savedInstanceState == null){
val bundle = bundleOf("some_int" to 0)
supportFragmentManager.commit {
setReorderingAllowed(true)
add<ExampleFragment>(R.id.fragment_container_view,args = bundle)
}
}
}
}
然后通过调用requireArguments()从fragment中获取Bundle,并且可以使用相应的getter方法来
获取每一个参数。
class ExampleFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val someInt = requireArguments().get("some_int")
...
}
}
更多推荐

所有评论(0)