好的,我来给你一个完整的Fragment Demo,从简单到复杂,并详细讲解每个部分。
一、最简单的Fragment Demo
1. 创建Fragment布局文件
res/layout/fragment_demo.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:orientation="vertical"
android:padding="16dp"
android:gravity="center">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是Fragment"
android:textSize="24sp"
android:textColor="@android:color/black" />
<Button
android:id="@+id/btn_click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="点击我" />
</LinearLayout>
2. 创建Fragment类
DemoFragment.java
java
public class DemoFragment extends Fragment {
// 1. 创建Fragment实例的方法(推荐写法)
public static DemoFragment newInstance() {
return new DemoFragment();
}
// 2. Fragment创建时调用(最早执行)
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 初始化数据,不涉及UI
}
// 3. 创建视图(最重要的方法)
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
// 加载布局文件
return inflater.inflate(R.layout.fragment_demo, container, false);
}
// 4. 视图创建完成后调用
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// 找到控件并设置点击事件
TextView tvTitle = view.findViewById(R.id.tv_title);
Button btnClick = view.findViewById(R.id.btn_click);
btnClick.setOnClickListener(v -> {
tvTitle.setText("按钮被点击了!");
});
}
}
3. 在Activity中使用Fragment
activity_main.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:orientation="vertical">
<!-- 方式1:通过标签静态添加Fragment -->
<fragment
android:id="@+id/fragment_static"
android:name="com.example.DemoFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<!-- 方式2:FrameLayout作为Fragment容器 -->
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="@+id/btn_add_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="动态添加Fragment" />
</LinearLayout>
MainActivity.java
java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 动态添加Fragment
Button btnAdd = findViewById(R.id.btn_add_fragment);
btnAdd.setOnClickListener(v -> {
// 开始Fragment事务
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, new DemoFragment()) // 替换容器内容
.addToBackStack(null) // 加入返回栈
.commit(); // 提交事务
});
}
}
二、带参数传递的Fragment Demo(实际开发常用)
1. 带参数的Fragment
UserDetailFragment.java
java
public class UserDetailFragment extends Fragment {
private TextView tvUserName, tvUserAge;
// 定义参数key
private static final String ARG_USER_NAME = "user_name";
private static final String ARG_USER_AGE = "user_age";
// 推荐:通过newInstance传递参数
public static UserDetailFragment newInstance(String name, int age) {
UserDetailFragment fragment = new UserDetailFragment();
// 使用Bundle传递参数
Bundle args = new Bundle();
args.putString(ARG_USER_NAME, name);
args.putInt(ARG_USER_AGE, age);
fragment.setArguments(args); // 设置参数
return fragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_user_detail, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
tvUserName = view.findViewById(R.id.tv_user_name);
tvUserAge = view.findViewById(R.id.tv_user_age);
// 获取传递的参数
if (getArguments() != null) {
String name = getArguments().getString(ARG_USER_NAME);
int age = getArguments().getInt(ARG_USER_AGE);
tvUserName.setText("姓名:" + name);
tvUserAge.setText("年龄:" + age);
}
}
}
2. 使用方式
java
// 在Activity或其他Fragment中
UserDetailFragment fragment = UserDetailFragment.newInstance("张三", 25);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment)
.commit();
三、Fragment与Activity通信的Demo
1. Fragment定义接口
CommunicationFragment.java
java
public class CommunicationFragment extends Fragment {
private EditText etInput;
private Button btnSend;
private OnDataSendListener listener;
// 定义通信接口
public interface OnDataSendListener {
void onDataSend(String data);
}
// 绑定Activity时调用
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
// 检查Activity是否实现了接口
if (context instanceof OnDataSendListener) {
listener = (OnDataSendListener) context;
} else {
throw new RuntimeException("Activity必须实现OnDataSendListener");
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_communication, container, false);
etInput = view.findViewById(R.id.et_input);
btnSend = view.findViewById(R.id.btn_send);
btnSend.setOnClickListener(v -> {
String data = etInput.getText().toString();
if (listener != null) {
listener.onDataSend(data); // 发送数据给Activity
}
});
return view;
}
}
2. Activity实现接口
MainActivity.java
java
public class MainActivity extends AppCompatActivity
implements CommunicationFragment.OnDataSendListener {
private TextView tvReceived;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvReceived = findViewById(R.id.tv_received);
// 添加Fragment
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, new CommunicationFragment())
.commit();
}
}
@Override
public void onDataSend(String data) {
// 接收Fragment发送的数据
tvReceived.setText("收到:" + data);
// 可以Toast提示
Toast.makeText(this, "收到:" + data, Toast.LENGTH_SHORT).show();
}
}
四、Fragment生命周期详解
完整生命周期Demo
java
public class LifecycleDemoFragment extends Fragment {
private static final String TAG = "LifecycleDemo";
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
Log.d(TAG, "1. onAttach - Fragment与Activity绑定");
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "2. onCreate - 创建Fragment,初始化数据");
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
Log.d(TAG, "3. onCreateView - 创建视图");
return inflater.inflate(R.layout.fragment_demo, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.d(TAG, "4. onViewCreated - 视图已创建,可以操作UI");
}
@Override
public void onStart() {
super.onStart();
Log.d(TAG, "5. onStart - Fragment可见");
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "6. onResume - Fragment获得焦点,可交互");
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG, "7. onPause - Fragment失去焦点");
}
@Override
public void onStop() {
super.onStop();
Log.d(TAG, "8. onStop - Fragment不可见");
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG, "9. onDestroyView - 销毁视图");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "10. onDestroy - 销毁Fragment");
}
@Override
public void onDetach() {
super.onDetach();
Log.d(TAG, "11. onDetach - Fragment与Activity解绑");
}
}
生命周期流程图
Activity创建
↓
onAttach() ← Fragment与Activity绑定
↓
onCreate() ← 初始化数据
↓
onCreateView() ← 创建视图(返回View)
↓
onViewCreated()← 视图创建完成,操作UI
↓
onStart() ← Fragment可见
↓
onResume() ← Fragment可交互
↓
【运行中】
↓
onPause() ← 失去焦点(如另一个Activity弹窗)
↓
onStop() ← 完全不可见
↓
onDestroyView()← 销毁视图
↓
onDestroy() ← 销毁Fragment
↓
onDetach() ← 与Activity解绑
五、实际使用建议
1. Fragment最佳实践模板
java
public class BestPracticeFragment extends Fragment {
// 1. 使用newInstance传递参数
public static BestPracticeFragment newInstance(String param) {
BestPracticeFragment fragment = new BestPracticeFragment();
Bundle args = new Bundle();
args.putString("param", param);
fragment.setArguments(args);
return fragment;
}
// 2. 声明View变量
private View rootView;
private TextView tvContent;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
// 缓存View
if (rootView == null) {
rootView = inflater.inflate(R.layout.fragment_best, container, false);
}
return rootView;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// 初始化控件
tvContent = view.findViewById(R.id.tv_content);
// 获取参数
if (getArguments() != null) {
String param = getArguments().getString("param");
tvContent.setText(param);
}
}
// 提供更新UI的方法
public void updateContent(String newContent) {
if (tvContent != null) {
tvContent.setText(newContent);
}
}
}
2. Fragment事务注意事项
java
// ✅ 正确:使用tag标记Fragment,避免重复添加
String tag = "demo_fragment";
Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
if (fragment == null) {
fragment = new DemoFragment();
getSupportFragmentManager()
.beginTransaction()
.add(R.id.container, fragment, tag)
.commit();
}
// ✅ 正确:使用commitAllowingStateLoss()避免状态丢失异常
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, newFragment)
.commitAllowingStateLoss();
// ❌ 错误:不要在onCreateView中操作FragmentTransaction
// ✅ 正确:在Activity的onCreate中,或使用post延迟执行
rootView.post(() -> {
getChildFragmentManager().beginTransaction()...
});
总结要点
- 创建Fragment :继承Fragment,实现
onCreateView - 使用Fragment :通过
FragmentTransaction的add/replace方法 - 传递参数 :使用
setArguments(Bundle),不要用构造方法 - 与Activity通信 :定义接口,在
onAttach中绑定 - 生命周期:理解11个生命周期方法,知道什么时候做什么
- 返回栈 :
addToBackStack(null)可以让用户按返回键回到上一个Fragment