一句话总结:
Fragment 是 Android 的“界面积木块”,可以像拼乐高一样,灵活组合、复用、动态切换界面,适合多屏适配和模块化开发。
Fragment 的两种使用姿势:
1. 静态加载(直接嵌在布局里)
-
适用场景:界面固定,不需要动态切换(比如平板左侧固定菜单栏)。
-
步骤:
-
定义 Fragment 的布局文件(如
fragment_my.xml)。 -
在 Activity 的布局文件中直接声明 Fragment:
<!-- activity_main.xml --> <fragment android:id="@+id/my_fragment" android:name="com.example.MyFragment" <!-- Fragment 类名 --> android:layout_width="match_parent" android:layout_height="match_parent" />运行 HTML
-
Fragment 类实现:
class MyFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // 加载布局文件 return inflater.inflate(R.layout.fragment_my, container, false) } }
-
2. 动态加载(灵活切换)
-
适用场景:根据用户操作切换不同界面(如底部导航栏切换页面)。
-
步骤:
-
在 Activity 的布局中预留容器(如
FrameLayout):<!-- activity_main.xml --> <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" />运行 HTML
-
在 Activity 中动态添加/替换 Fragment:
// 初始化 Fragment val fragment = MyFragment() // 使用 FragmentTransaction 操作 supportFragmentManager.beginTransaction() .replace(R.id.fragment_container, fragment) // 替换容器中的内容 .addToBackStack("my_fragment_tag") // 添加到返回栈(按返回键可回退) .commit()
-
Fragment 和 Activity 的通信
1. Activity → Fragment
-
通过 Bundle 传参数:
// 在 Activity 中 val fragment = MyFragment().apply { arguments = Bundle().apply { putString("key", "我是参数") } } // 在 Fragment 的 onCreateView 中获取参数 val value = arguments?.getString("key")
2. Fragment → Activity
-
通过接口回调(避免直接操作 Activity):
// 在 Fragment 中定义接口 interface OnButtonClickListener { fun onButtonClick(message: String) } class MyFragment : Fragment() { private var listener: OnButtonClickListener? = null override fun onAttach(context: Context) { super.onAttach(context) listener = context as? OnButtonClickListener // Activity 实现接口 } // 按钮点击时回调 button.setOnClickListener { listener?.onButtonClick("用户点击了按钮") } } // 在 Activity 中实现接口 class MainActivity : AppCompatActivity(), MyFragment.OnButtonClickListener { override fun onButtonClick(message: String) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } }
Fragment 的状态保存
-
临时数据保存(如输入框内容):
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putString("input_text", editText.text.toString()) } override fun onViewStateRestored(savedInstanceState: Bundle?) { super.onViewStateRestored(savedInstanceState) val text = savedInstanceState?.getString("input_text") editText.setText(text) }
注意事项
-
避免内存泄漏:
- 在
onDestroyView中释放资源(如取消网络请求)。 - 不要在 Fragment 中直接持有 Activity 的强引用。
- 在
-
FragmentTransaction 的提交时机:
- 不要在
onSaveInstanceState之后提交事务(会导致崩溃)。 - 使用
commitAllowingStateLoss()允许状态丢失(不推荐,慎用)。
- 不要在
-
嵌套 Fragment 要谨慎:
- 嵌套过深会导致管理复杂,建议用
ViewPager2或Navigation库替代。
- 嵌套过深会导致管理复杂,建议用
总结
-
Fragment 是界面模块化的利器:
- 静态加载:适合固定布局。
- 动态加载:灵活切换,适合交互复杂的场景。
-
通信要规范:用接口回调,别直接操作。
-
生命周期要管理:注意资源释放和状态保存。
口诀:
- “静态布局直接嵌,动态替换用容器”
- “传参 Bundle 接口回调,生命周期别乱搞”