Fragment 基础
本教程共 100 篇 · 第 39 篇 · 更新于 2026-07-28 · 约 8 分钟阅读
39. Fragment 基础
本节目标:理解 Fragment 是什么、它和 Activity 的关系、生命周期怎么走,学会创建 Fragment 并把它放到 Activity 里。
Fragment 是什么
打个比方:Activity 是一张大桌子,Fragment 是桌面上的模块化隔板。你可以把桌面分成几个区域,每个区域放一块隔板(Fragment),隔板上有自己的内容和功能。想换布局?把隔板挪一挪就行,不用换整张桌子。
Fragment(片段)是 Activity 界面中可重复使用的一部分。它有自己的布局、自己的生命周期、能处理自己的输入事件,但不能独立存在,必须由 Activity 或其他 Fragment 托管。
Fragment 的视图会变成宿主视图层级的一部分。
为什么需要 Fragment
最直接的好处是适配不同屏幕。同一个应用,在手机上你可能想一次显示一个界面,在平板上想并排显示两个界面。用 Fragment 就能轻松实现—同一套 Fragment 代码,大屏并排放两个,小屏只放一个加导航切换。
其次,Fragment 让界面模块化。把复杂的界面拆成几个 Fragment,每个管自己的逻辑,比把所有东西塞在一个 Activity 里好维护得多。
创建一个 Fragment
继承 Fragment(注意用 androidx.fragment.app.Fragment,别用旧版的 android.app.Fragment),实现 onCreateView() 返回布局:
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
class HomeFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// 加载 Fragment 的布局
return inflater.inflate(R.layout.fragment_home, container, false)
}
}
布局文件 fragment_home.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是首页 Fragment"
android:textSize="20sp" />
</LinearLayout>
Note
inflate()的第三个参数false很关键。它表示「加载布局但不自动添加到 container」。Fragment 系统会自己处理添加时机,你手动传true会出问题。
在 Activity 中使用 Fragment
静态加载
直接在 Activity 的布局里用 <fragment> 标签声明:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="@+id/home_fragment"
android:name="com.example.app.HomeFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
android:name 指定 Fragment 类的全路径。这种方式简单,但运行时不能替换。
动态加载
动态加载可以在运行时切换 Fragment,这才是 Fragment 的核心玩法。需要一个容器(通常是 FrameLayout)放 Fragment:
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
在 Activity 里用 FragmentManager 做事务:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 防止重复添加
if (savedInstanceState == null) {
supportFragmentManager.commit {
replace(R.id.fragment_container, HomeFragment())
}
}
}
}
Tip
supportFragmentManager.commit { }是 Fragment KTX 提供的简化写法,等价于beginTransaction()+ 一堆操作 +commit()。需要加implementation("androidx.fragment:fragment-ktx:1.8.5")依赖。
Fragment 生命周期
Fragment 的生命周期和 Activity 很像,但多几个方法。因为 Fragment 寄生在 Activity 上,它的生命周期受 Activity 影响。
完整流程:
onAttach -> onCreate -> onCreateView -> onViewCreated
-> onStart -> onResume -> onPause -> onStop
-> onDestroyView -> onDestroy -> onDetach
关键方法解释:
| 方法 | 作用 | 该做什么 |
|---|---|---|
onAttach() | Fragment 关联到 Activity | 获取 Activity 引用 |
onCreate() | Fragment 创建 | 初始化非视图数据 |
onCreateView() | 创建视图 | 加载布局 |
onViewCreated() | 视图创建完毕 | 初始化视图控件、设监听 |
onStart() | 可见 | |
onResume() | 可交互 | |
onPause() | 失去焦点 | 保存数据 |
onStop() | 不可见 | |
onDestroyView() | 视图销毁 | 清理视图引用 |
onDestroy() | Fragment 销毁 | 清理资源 |
onDetach() | 脱离 Activity | 释放 Activity 引用 |
Warning
- 注意
onCreateView()和onViewCreated()的分工。在onCreateView()里只加载布局,在onViewCreated()里再findViewById或初始化控件。如果 Fragment 被加回返回栈,onDestroyView()会调用但onDestroy()不会—视图销毁了但 Fragment 实例还在。这时如果你在onDestroyView()里没清理对视图的引用,就会内存泄漏。
三种状态
Fragment 简化来看有三种状态:
- Resumed(恢复):可见且可交互。
- Started(已启动):可见但不可交互。
- Stopped(已停止):不可见(宿主 Activity 被停止,或 Fragment 被移除但压入返回栈)。
被停止的 Fragment 仍然活着(状态和数据保留),但如果 Activity 被杀,Fragment 也会被杀。
FragmentManager
FragmentManager 是管理 Activity 中所有 Fragment 的「大管家」。通过 supportFragmentManager(AppCompatActivity 里)或 parentFragmentManager(Fragment 里)获取。
它能做的事:
- 通过
findFragmentById()/findFragmentByTag()找到已存在的 Fragment - 开启事务来添加、替换、移除 Fragment
- 管理返回栈
// 找到容器里当前的 Fragment
val current = supportFragmentManager.findFragmentById(R.id.fragment_container)
Note
- 现代 Android 开发中,如果你的界面完全是 Compose 写的,可能不太会直接用 Fragment。但 Navigation Compose 底层、很多第三方库、以及需要混合 View 和 Compose 的场景,仍然依赖 Fragment。理解它是基本功。
小结
Fragment 是 Activity 界面的模块化拆分,有自己的布局和生命周期,但不能独立存在。静态加载简单但不能替换,动态加载通过 FragmentManager 做事务来切换。生命周期比 Activity 多了 onCreateView / onDestroyView 等视图相关方法,要注意在 onDestroyView 里清理视图引用。