一句话说透Android里面的Fragment的使用方式

399 阅读2分钟

一句话总结

Fragment 是 Android 的“界面积木块”,可以像拼乐高一样,灵活组合、复用、动态切换界面,适合多屏适配和模块化开发。


Fragment 的两种使用姿势

1. 静态加载(直接嵌在布局里)

  • 适用场景:界面固定,不需要动态切换(比如平板左侧固定菜单栏)。

  • 步骤

    1. 定义 Fragment 的布局文件(如 fragment_my.xml)。

    2. 在 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

    3. Fragment 类实现

      class MyFragment : Fragment() {
          override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
              // 加载布局文件
              return inflater.inflate(R.layout.fragment_my, container, false)
          }
      }
      

2. 动态加载(灵活切换)

  • 适用场景:根据用户操作切换不同界面(如底部导航栏切换页面)。

  • 步骤

    1. 在 Activity 的布局中预留容器(如 FrameLayout):

      <!-- activity_main.xml -->
      <FrameLayout
          android:id="@+id/fragment_container"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />
      

      运行 HTML

    2. 在 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)
    }
    

注意事项

  1. 避免内存泄漏

    • 在 onDestroyView 中释放资源(如取消网络请求)。
    • 不要在 Fragment 中直接持有 Activity 的强引用。
  2. FragmentTransaction 的提交时机

    • 不要在 onSaveInstanceState 之后提交事务(会导致崩溃)。
    • 使用 commitAllowingStateLoss() 允许状态丢失(不推荐,慎用)。
  3. 嵌套 Fragment 要谨慎

    • 嵌套过深会导致管理复杂,建议用 ViewPager2 或 Navigation 库替代。

总结

  • Fragment 是界面模块化的利器

    • 静态加载:适合固定布局。
    • 动态加载:灵活切换,适合交互复杂的场景。
  • 通信要规范:用接口回调,别直接操作。

  • 生命周期要管理:注意资源释放和状态保存。

口诀

  • “静态布局直接嵌,动态替换用容器”
  • “传参 Bundle 接口回调,生命周期别乱搞”