首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

  • 24-11-26 09:05
  • 4296
  • 12571
juejin.cn

1. Fragment 是什么?

Fragment 直译为 “碎片 ”或 “片段”,是一种可嵌入在 Activity 中的 UI 片段,可以看作是 Activity 的模块化部分,用于构建动态和灵活的用户界面,更加合理和充分利用大屏幕的空间。

Fragment 不能独立存在,必须嵌入到 Activity 中,其生命周期与所在的 Activity 紧密相关。

Fragment 用法类似于一个自定义控件。

主要特点:

模块化:Fragment 允许开发者将应用界面划分为多个独立、可重用的部分,每个 Fragment 都可以定义自己的布局和行为。

灵活性:Fragment 可以在运行时动态添加到 Activity 布局中,也可以在不同的 Activity 中重复使用,从而实现灵活的UI布局和界面复用。

适应不同屏幕尺寸:Fragment 非常适合在大屏幕设备(如平板电脑)上实现多窗格UI设计,同时也可以在小屏幕设备上适配不同的屏幕尺寸和方向。

生命周期管理:Fragment 拥有自己的生命周期,与 Activity 的生命周期类似但更为复杂。系统负责管理 Fragment 的生命周期,开发者可以在相应的生命周期回调方法中进行初始化、视图创建、数据加载等操作。

2. Fragment 的使用方式

2.1 静态添加 Fragment

新建左侧 Fragment 布局 left_fragment.xml,新建右侧 Fragment 布局 right_fragment.xml。

新建一个 LeftFragment 类,继承自 Fragment(AndroidX) 类,将定义的布局动态加载进来。

java
代码解读
复制代码
public class LeftFragment extends Fragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.left_fragment,container,false);//动态加载布局 return view; } }

新建一个 RightFragment 类。

修改 activity_main.xml,需要通过 android: name 显式声明要添加的 fragment 类名,一定要加类的包名:

xml
代码解读
复制代码
"1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/left_fragment" android:name="com.example.trainning.LeftFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> <fragment android:id="@+id/right_fragment" android:name="com.example.trainning.RightFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> LinearLayout>

2.2 动态添加 Fragment

新建 another_right_fragment.xml,新建 AnotherRightFragment,代码省略。

修改 activity_main.xml ,

xml
代码解读
复制代码
"1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/left_fragment" android:name="com.example.trainning.LeftFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> <FrameLayout android:id="@+id/right_layout" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> LinearLayout>

在 Activity 中动态添加 Fragment:

  1. 创建待添加的 fragment 实例。
  2. 获取 FragmentManager,调用 getSupportFragmentManager。
  3. 开启一个事务 beginTransaction。
  4. 替换 fragment,replace。
  5. 提交事务 。
java
代码解读
复制代码
public class NormalFragmentActivity extends AppCompatActivity { private Button leftFragmentButton; private View leftFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_normal_fragment); leftFragment = findViewById(R.id.left_fragment); leftFragmentButton = leftFragment.findViewById(R.id.left_fragment_button); replaceFragment(new RightFragment()); leftFragmentButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { replaceFragment(new AnotherRightFragment()); } }); } private void replaceFragment(Fragment fragment) { FragmentManager fragmentManager = getSupportFragmentManager();// 获取 FragmentManager FragmentTransaction transaction = fragmentManager.beginTransaction();// 开启一个事务 beginTransaction() transaction.replace(R.id.right_layout, fragment); transaction.commit(); } }

FragmentManager 用于管理 Fragment 的生命周期、交互和事务。Activity 是 FragmentManager 的宿主环境类。

FragmentTransaction:提供了一系列的方法来执行对 Fragment 的事务性操作,用来管理 Fragment 的添加、移除、替换以及执行其他操作。

事务的提交是通过调用 commit 方法完成的。一旦事务被提交,系统就会按照你指定的操作顺序来更新Fragment的状态。

“事务”(Transaction)是指一系列对Fragment进行的操作,这些操作被封装在一个单独的执行单元中,并且要么全部成功执行,要么全部回滚(即不执行任何操作)。这种机制确保了Fragment状态的一致性,防止了因部分操作失败而导致的界面不一致或应用崩溃。

3. 在 Fragment 里模拟返回栈

模拟返回栈对于 Fragment 的管理是非常重要的。通过模拟返回栈,你可以让用户在 Fragment 之间进行导航,并且能够通过按下 back 键返回到之前的 Fragment 状态,而不是直接关闭 Activity。

在 Fragment 事务中,你使用 addToBackStack() 方法将 Fragment 事务添加到返回栈中。这样,当用户按下后退键时,系统会自动回退到上一个 Fragment。

java
代码解读
复制代码
private void replaceFragment(Fragment fragment) { FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); transaction.replace(R.id.right_layout,fragment); transaction.addToBackStack(null); //接受一个名字描述返回栈的状态 transaction.commit(); }

addToBackStack 可以传入一个 null 作为名称,或者传入一个唯一的字符串来标识这个返回栈条目,如:

java
代码解读
复制代码
fragmentTransaction.addToBackStack("my_unique_back_stack_entry");

这个名称在调试时可能会派上用场,它可以帮助你识别返回栈中的不同条目。在大多数情况下,传入 null 就足够了,因为系统会自动为每个返回栈条目分配一个唯一的 ID。

4. Fragment 和 Activity 之间的通信

在 Activity 中获得 Fragment 实例:

java
代码解读
复制代码
LeftFragment leftFragment = (LeftFragment)getSupportFragmentManager().findFragmentById(R.id.left_fragment);

在 Fragment 中获得相关联 Activity 的实例:

java
代码解读
复制代码
NormalFragmentActivity activity = (NormalFragmentActivity) getActivity();

Fragment 中需要使用 Context 对象时,也可以使用 getActivity()方法。

下面介绍两种常用的通信方式:

4.1 Activity 使用 Bundle 向 Fragment 传递数据

在 Activity 中创建 Fragment 实例并传递数据:

java
代码解读
复制代码
MyFragment myFragment = new MyFragment(); Bundle bundle = new Bundle(); bundle.putString("key", "value"); myFragment.setArguments(bundle); replaceFragment(myFragment);

在 Fragment 中接收数据:

java
代码解读
复制代码
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle arguments = getArguments(); if (arguments != null) { String value = arguments.getString("key"); // 使用传递过来的数据 } }

4.2 Fragment 使用接口向 Activity 传递数据

定义接口:

java
代码解读
复制代码
public interface IFragmentCallback { void onFragmentChanged(); }

Activity:

java
代码解读
复制代码
public class FragmentActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_normal_fragment); LeftFragment leftFragment = new LeftFragment(); leftFragment.setFragmentCallback(new IFragmentCallback() { @Override public void onFragmentChanged() { Log.i("this", "click button in the fragment"); } }); } }

Fragment:

java
代码解读
复制代码
public class LeftFragment extends Fragment { private IFragmentCallback fragmentCallback; View view; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { if (view == null) { view = inflater.inflate(R.layout.left_fragment, container,false); } Button button = view.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { fragmentCallback.onFragmentChanged(); } }); return view; } public void setFragmentCallback(IFragmentCallback fragmentCallback) { this.fragmentCallback = fragmentCallback; } }

当点击 Fragment 中的按钮时,Activity 中就会收到回调,并可以处理相应的逻辑。

除此之外,activity 与 fragment 之间的通信还可以采用其他方案,如 EventBus、LiveData 等,其本质上都是使用了观察者模式。

5. Fragment 的生命周期

Fragment 的生命周期可参考:fragment 生命周期  |  Android Developers ,此文章中进行了详细解析。

image.png

后续会专门出文章对 Fragment 进行源码分析。

注:本文转载自juejin.cn的liang_jy的文章"https://juejin.cn/post/7440874036643528758"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

140
Android
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top