01-Fragment基础与加载方式
Fragment 基础与加载方式
1. Fragment 是什么
Fragment 是 Android 中用于构建可复用 UI 模块的组件。它通常表示一个界面片段,拥有自己的布局、生命周期和输入事件处理能力,但它不能独立存在,必须依附于 Activity 或另一个 Fragment。
更准确的理解是:
Activity = 宿主与页面级容器
Fragment = 页面中的可复用 UI 与逻辑单元
View = 更底层的 UI 绘制与交互单元
Fragment 适合用在:
- 一个 Activity 中切换多个页面区域,例如首页 Tab。
- 适配平板、折叠屏、横竖屏布局。
- 把复杂页面拆成多个独立模块。
- 和 Navigation Component 配合管理页面栈。
2. Fragment 是“第五大组件”吗?
面试中经常有人说 Fragment 是 Android 的“第五大组件”,这个说法可以作为民间记忆法,但不是官方组件分类。
Android 传统四大组件是:
| 组件 | 是否需要在 Manifest 中声明 | 是否可以独立被系统调度 | 典型职责 |
|---|---|---|---|
| Activity | 是 | 是 | 展示界面 |
| Service | 是 | 是 | 后台或前台任务 |
| BroadcastReceiver | 是/动态注册 | 是 | 接收广播 |
| ContentProvider | 是 | 是 | 跨进程数据共享 |
| Fragment | 否 | 否 | Activity 内的 UI 模块 |
所以更严谨的回答是:
Fragment 有生命周期,使用频率很高,可以灵活嵌入 Activity,但它不是与四大组件同级的系统组件,而是依附于宿主的 UI 模块。
3. 使用 AndroidX Fragment
现代项目应使用 AndroidX 版本:
import androidx.fragment.app.Fragment
不要再使用平台版本:
// 不推荐:android.app.Fragment 已废弃
import android.app.Fragment
依赖示例:
implementation("androidx.fragment:fragment-ktx:<latest-version>")
4. Fragment 的加载方式
Fragment 加载到宿主中,主要有两类方式:XML 声明和代码动态添加。
4.1 XML 静态声明:推荐 FragmentContainerView
旧资料中常见 <fragment> 标签:
<fragment
android:id="@+id/my_fragment"
android:name="com.example.MyFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
现在更推荐使用 FragmentContainerView,因为它更符合 FragmentManager 的状态管理规则:
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container"
android:name="com.example.HomeFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
适合场景:页面固定只有一个 Fragment,不需要复杂切换。
4.2 动态加载:FragmentManager + FragmentTransaction
动态加载更常见,适合运行时切换页面:
supportFragmentManager.commit {
replace(R.id.fragment_container, HomeFragment())
}
如果没有使用 KTX,也可以写成:
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, HomeFragment())
transaction.commit()
常见操作:
| 方法 | 作用 | 是否销毁原 Fragment 视图 |
|---|---|---|
add() |
添加 Fragment | 否 |
remove() |
移除 Fragment | 是 |
replace() |
替换容器中的 Fragment | 通常会移除旧 Fragment |
hide() / show() |
隐藏或显示已添加 Fragment 的 View | 否 |
detach() / attach() |
分离或重新附加 Fragment 的 View | detach 会销毁 View |
5. Fragment 与 ViewPager / ViewPager2
旧资料中常见:
FragmentPagerAdapter:页面少时使用。FragmentStatePagerAdapter:页面多时使用。
这个结论在老项目中仍能看懂,但新项目应该改为:
ViewPager 已被 ViewPager2 替代
FragmentPagerAdapter / FragmentStatePagerAdapter 已废弃
ViewPager2 + FragmentStateAdapter 是当前推荐组合
示例:
class HomePagerAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
override fun getItemCount(): Int = 3
override fun createFragment(position: Int): Fragment {
return when (position) {
0 -> HomeFragment()
1 -> MessageFragment()
else -> MineFragment()
}
}
}
配合 TabLayout:
viewPager.adapter = HomePagerAdapter(this)
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = when (position) {
0 -> "首页"
1 -> "消息"
else -> "我的"
}
}.attach()
6. 面试回答模板
问题:Fragment 为什么常被称为第五大组件?
可以这样回答:
这个说法不是官方分类。Fragment 不能独立运行,必须依附 Activity 或父 Fragment,所以它不是和四大组件同级的系统组件。但 Fragment 有自己的生命周期、布局和事件处理能力,使用频率非常高,常用于页面模块化、Tab 切换、平板和折叠屏适配,因此面试中有人把它称为第五大组件。
问题:Fragment 如何加载到 Activity 中?
可以这样回答:
主要有 XML 静态声明和代码动态添加两种。老写法用
<fragment>,新项目更推荐FragmentContainerView。动态加载通过FragmentManager开启FragmentTransaction,使用add、replace、show、hide、detach、attach等方法提交事务。如果是页面导航,推荐优先考虑 Jetpack Navigation。