[Android 从零到一] Fragment 基础与生命周期
Fragment 基础与生命周期
一、背景
Android 从 API 11(Android 3.0)引入了 Fragment,最初是为了在大屏平板上实现灵活的 UI 布局。如今它已成为 Android 开发的核心组件,即使是手机上的单屏 App 也广泛使用 Fragment 来管理界面。
简单来说,Fragment 是一种可以嵌入到 Activity 中的 UI 片段,它有自己的布局、生命周期和事件处理能力。
二、核心概念
2.1 什么是 Fragment?
Fragment 是 Activity 中 UI 的一个行为部分。可以理解为"子 Activity"——它有自己的布局和生命周期,但必须依赖于 Activity 才能存在。
2.2 Fragment 的生命周期
Fragment 有 7 个核心生命周期回调,与 Activity 紧密关联:
onAttach()— Fragment 被关联到 ActivityonCreate()— 初始化 Fragment(非 UI 相关)onCreateView()— 加载布局文件onViewCreated()— 视图创建完毕,初始化 UI 控件onStart()— Fragment 可见onResume()— Fragment 可与用户交互onPause()— Fragment 部分不可见onStop()— Fragment 完全不可见onDestroyView()— 视图被销毁onDestroy()— Fragment 销毁onDetach()— 与 Activity 解除关联
2.3 生命周期联动
当宿主 Activity 经历其生命周期时,Fragment 也会跟随变化。一个关键点是 onCreateView 和 onDestroyView 成对出现——每次 Fragment 离开屏幕时视图会被销毁,但 Fragment 实例可能仍然存活(比如被回退栈保留)。
三、代码实战(Kotlin)
3.1 定义 Fragment
class MyFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// 加载布局文件
return inflater.inflate(R.layout.fragment_my, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 初始化 UI,findViewById 已弃用,用 View Binding
val tvTitle = view.findViewById<TextView>(R.id.tv_title)
tvTitle.text = "Hello Fragment"
}
}
3.2 布局文件
<!-- fragment_my.xml -->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="默认标题"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_margin="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
3.3 在 Activity 中添加 Fragment
方法一:静态添加(在布局中声明)
<!-- activity_main.xml -->
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container"
android:name="com.example.app.MyFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
方法二:动态添加(Kotlin 代码)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
// 动态添加 Fragment
supportFragmentManager.commit {
replace(R.id.fragment_container, MyFragment())
addToBackStack(null) // 添加到回退栈
}
}
}
}
3.4 Fragment 与 Activity 通信
// Fragment 定义接口
class ListFragment : Fragment() {
interface OnItemSelectedListener {
fun onItemSelected(itemId: Int)
}
private var listener: OnItemSelectedListener? = null
override fun onAttach(context: Context) {
super.onAttach(context)
// 确保 Activity 实现了接口
listener = context as? OnItemSelectedListener
}
override fun onDetach() {
super.onDetach()
listener = null
}
fun onItemClicked(id: Int) {
listener?.onItemSelected(id)
}
}
// Activity 实现接口
class MainActivity : AppCompatActivity(), ListFragment.OnItemSelectedListener {
override fun onItemSelected(itemId: Int) {
// 切换到详情 Fragment
supportFragmentManager.commit {
replace(R.id.detail_container, DetailFragment.newInstance(itemId))
addToBackStack("detail")
}
}
}
四、避坑指南
- Fragment 重叠问题:Activity 重建时系统会恢复 Fragment,如果在
onCreate中再次 commit 会导致重叠。解决办法:加上savedInstanceState == null判断。 - FragmentManager 的生命周期:不要在 Activity 的
onSaveInstanceState之后 commit 事务,会抛IllegalStateException。可以用commitAllowingStateLoss()但需谨慎。 - 空构造函数要求:Fragment 必须有一个公开的无参构造函数,系统在重建时会通过反射调用它。不要用带参数的构造器,用
newInstance()静态方法 +Bundle传参。 - View Binding 与 Fragment:在
onCreateView中 inflate 布局,在onDestroyView中置空 binding 引用防止内存泄漏。
五、总结
Fragment 是 Android 开发的基础组件,掌握它的生命周期和通信机制至关重要。核心要点:
- 生命周期与 Activity 联动,但有自己的
onCreateView/onDestroyView过程 - 动态添加比静态声明更灵活,搭配
addToBackStack实现导航 - Fragment 与 Activity 通信通过接口回调,避免直接持有 Activity 引用
- 使用
FragmentContainerView替代旧的<fragment>标签
下一期预告:RecyclerView 入门,敬请期待

浙公网安备 33010602011771号