Android Fragment全面解析

Fragment(碎片)是 Android 开发中核心的模块化组件,自 Android 3.0(API 11)引入以来,一直是解决屏幕适配、页面模块化拆分的核心方案。相比于 Activity,Fragment 更轻量、可复用性更强,能让复杂页面拆分为独立模块,大幅提升代码的可维护性。

一、什么是Fragment,Fragment的优势

Fragment 是嵌入在Activity中的模块化组件,拥有自己的生命周期、布局和逻辑,但不能独立存在,依赖 Activity 的 Contenxt,必须依附于 Activity。可以把 Activity 想象成一个相框,而 Fragment 就是相框里的照片。一个 Activity可以包含多个 Fragment,一个 Fragment 也可以被多个 Activity 复用。

Fragment 的优势在于:

  • 模块化:复杂页面(如电商详情页)可拆分为 "标题 Fragment + 商品信息 Fragment + 评论 Fragment",各模块独立开发维护
  • 复用性强:同一个 Fragment 可在不同 Activity 中复用(如搜索框 Fragment,既可以在首页用,也可以在个人中心用)
  • 适配多屏幕:平板 / 折叠屏可同时显示多个 Fragment,手机端仅显示一个,无需写两套布局
  • 灵活的生命周期:可独立控制显示 / 隐藏 / 替换,不影响 Activity 的生命周期

二、Fragment的基本使用

Fragment 分为静态注册(XML)和动态注册两种方式

创建基础 Fragment 类

java 复制代码
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class FirstFragment extends Fragment {
    // 静态创建实例(推荐:避免直接new,统一传参入口)
    public static FirstFragment newInstance(String msg) {
        FirstFragment fragment = new FirstFragment();
        Bundle args = new Bundle();
        args.putString("msg", msg);
        fragment.setArguments(args);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        // 加载Fragment布局(第三个参数必须为false,避免直接添加到容器)
        return inflater.inflate(R.layout.fragment_first, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // 初始化控件、数据(推荐在onViewCreated中做,而非onCreateView)
        if (getArguments() != null) {
            String msg = getArguments().getString("msg");
            // 绑定文本框等操作
        }
    }
}

Fragment 的布局文件(XML)

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="第一个Fragment"
        android:textSize="20sp" />

</LinearLayout>

在Activity的布局文件中静态注册 Fragment,适合固定不变的 Fragment,缺点是无法动态控制显示/隐藏

XML 复制代码
<!-- Activity的布局文件 activity_main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- 静态注册Fragment -->
    <fragment
        android:id="@+id/fragment_first"
        android:name="com.example.fragmentdemo.FirstFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

在代码中动态注册 Fragment

java 复制代码
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 1. 获取Fragment管理器(必须用getSupportFragmentManager,兼容低版本)
        FragmentManager fragmentManager = getSupportFragmentManager();
        // 2. 开启事务(Fragment操作必须通过事务)
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        
        // 3. 创建Fragment实例(推荐用newInstance传参)
        FirstFragment fragment = FirstFragment.newInstance("动态添加的Fragment");
        
        // 4. 执行操作:添加Fragment到指定容器(R.id.fl_container是Activity布局中的空容器)
        transaction.add(R.id.fl_container, fragment, "FirstFragment"); // tag用于后续查找
        
        // 可选:添加到回退栈(按返回键时恢复Fragment,而非退出Activity)
        transaction.addToBackStack("FirstFragment");
        
        // 5. 提交事务(必须调用,否则操作不生效)
        transaction.commit();
    }
}

Activity 布局中需要预留空容器

XML 复制代码
<!-- activity_main.xml -->
<FrameLayout
    android:id="@+id/fl_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

常用的事务操作API:

  • add():添加 Fragment 到容器(可叠加多个);
  • replace():替换容器中的 Fragment(先移除原有,再添加新的);
  • hide()/show():隐藏 / 显示 Fragment(不销毁生命周期);
  • remove():移除 Fragment(销毁生命周期);
  • addToBackStack():加入回退栈,支持返回键恢复。

三、Fragment的生命周期

Fragment 的生命周期有:

|--------------------------|------------------------------------|
| 方法 | 触发时机 |
| onAttach() | Fragment 与 Activity 绑定成功时(仅执行 1 次) |
| onCreate() | Fragment 创建时(仅执行 1 次) |
| onCreateView() | 创建 Fragment 布局时 |
| onActivityCreated()(已废弃) | Activity 的 onCreate 执行完成后 |
| onViewCreated() | onCreateView 执行完成后 |
| onStart() | Fragment 可见时 |
| onResume() | Fragment 可交互时 |
| onPause() | Fragment 失去焦点时 |
| onStop() | Fragment 不可见时 |
| onDestroyView() | Fragment 的布局被销毁时 |
| onDestroy() | Fragment 实例销毁时 |
| onDetach() | Fragment 与 Activity 解绑时 |

常见场景下的生命周期变化

  1. Fragment 首次添加到 Activity
XML 复制代码
onAttach → onCreate → onCreateView → onViewCreated → onStart → onResume
  1. 横竖屏切换
XML 复制代码
Fragment: onPause → onStop → onDestroyView → onDestroy → onDetach
Fragment: onAttach → onCreate → onCreateView → onViewCreated → onStart → onResume
  1. Fragment 被 replace
XML 复制代码
原有Fragment: onPause → onStop → onDestroyView
新Fragment: onAttach → onCreate → onCreateView → onViewCreated → onStart → onResume

返回键恢复时

XML 复制代码
新Fragment: onPause → onStop → onDestroyView
原有Fragment: onCreateView → onViewCreated → onStart → onResume

四、在Fragment中获取Activity结果

以前我们用 startActivityForResult,然后在 onActivityResult 里接数据。现在,官方推荐使用 ActivityResult API。

java 复制代码
// 1. 定义ActivityResultLauncher(作为Fragment的成员变量直接初始化)
private ActivityResultLauncher<Intent> mLauncher = registerForActivityResult(
    new ActivityResultContracts.StartActivityForResult(),
    result -> {
        if (result.getResultCode() == Activity.RESULT_OK) {
            Intent data = result.getData();
            if (data != null) {
                String resultStr = data.getStringExtra("result");
                // 处理返回结果
            }
        }
    }
);

// 2. 启动Activity
public void startSecondActivity() {
    Intent intent = new Intent(getActivity(), SecondActivity.class);
    intent.putExtra("data", "test");
    mLauncher.launch(intent);
}

五、Fragment之间的通信

1. 共享ViewModel

java 复制代码
// Fragment A 发送数据
val viewModel: SharedViewModel by activityViewModels()
viewModel.selectItem(item)

// Fragment B 接收数据
val viewModel: SharedViewModel by activityViewModels()
viewModel.selectedItem.observe(viewLifecycleOwner) { item ->
    // 更新 UI
}

2. Fragment Result API

发送方(Fragment A):

java 复制代码
setFragmentResult("requestKey", bundleOf("bundleKey" to "Hello!"))

接收方(Fragment B):

java 复制代码
setFragmentResultListener("requestKey") { key, bundle ->
    val result = bundle.getString("bundleKey")
    // 处理结果
}

六、Fragment实现滑动

滑动切换 Fragment 是高频场景,推荐使用ViewPager2,支持横向/纵向滑动、RecyclerView 复用机制

Activity 布局

XML 复制代码
<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/viewPager2"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

自定义 FragmentStateAdapter

java 复制代码
class MyAdapter(fragment: FragmentActivity) : FragmentStateAdapter(fragment) {
    override fun getItemCount(): Int = 3
    override fun createFragment(position: Int): Fragment = when(position) {
        0 -> ChatFragment()
        1 -> ContactFragment()
        else -> SettingFragment()
    }
}

Activity 中绑定 ViewPager2

java 复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    ViewPager2 viewPager2 = findViewById(R.id.viewPager2);
    // 设置适配器
    viewPager2.setAdapter(new MyFragmentAdapter(this));
    // 设置预加载页数(默认预加载1页,设为0可实现懒加载)
    viewPager2.setOffscreenPageLimit(0);
}
相关推荐
web_Hsir2 小时前
uniapp + vue2 + pfdjs + web-view 实现安卓、iOS App PDF预览
android·前端·uni-app
一起养小猫2 小时前
Flutter for OpenHarmony 实战:Container与Padding布局完全指南
android·flutter·harmonyos
HeDongDong-2 小时前
详解Kotlin的各种类(使用场景导向)
android·开发语言·kotlin
Whisper_Sy10 小时前
Flutter for OpenHarmony移动数据使用监管助手App实战 - 网络状态实现
android·java·开发语言·javascript·网络·flutter·php
ujainu11 小时前
Flutter + OpenHarmony 网格布局:GridView 与 SliverGrid 在鸿蒙设备内容展示中的应用
android·flutter·组件
龙之叶12 小时前
【Android Monkey源码解析五】- 异常处理
android·数据库
明道源码12 小时前
Android Studio AVD 模拟器的使用与配置
android·android studio
学海无涯书山有路13 小时前
Android FragmentContainerView 新手详解(Java 版)
android·java·开发语言
上海控安13 小时前
Android生态中的SDK安全问题解析
android·安全