当前位置: 首页 > news >正文

Android Fragment:详解,结合真实开发场景Navigation

目录

1)Fragment是什么
2)Fragment的应用场景
3)为什么使用Fragment?
4)Fragment如何使用
5)Fragment的生命周期
6)Android开发,建议是多个activity,还是activity结合fragment,优缺点如何?
7)Fragment和Activity的通讯、返回键如何处理
8)Navigation搭配Fragment使用后,事务是怎么样?

一、Fragment是什么


Fragment是Android中的一种组件,直译为“碎片”或“片段”,可以看作是Activity的模块化部分。

它主要用于承载一部分用户界面和逻辑,并可以在多个Activity中复用。Fragment具有自己的生命周期,能接收输入事件,可以在Activity运行时被添加、移除、替换或隐藏。此外,Fragment还允许开发者通过FragmentManager来管理其生命周期和事务,如添加、删除、替换Fragment等。

二、Fragment的应用场景


导航

  1. UI一:
    在这里插入图片描述
  2. UI二:
    在这里插入图片描述

三、为什么使用Fragment?


  1. 通过将复杂的界面拆分成多个Fragment,每个Fragment负责一部分UI和逻辑,可以提高代码的复用性和可维护性。不同的Fragment可以专注于处理特定的UI或逻辑,使得代码更加清晰和易于管理。
  2. Fragment可以被多个Activity复用,提高了代码的复用率。在模块化开发中,一个Fragment可以代表一个独立的业务模块,从而在不同的地方重复使用。

四、Fragment如何使用


4.1 Fragment一般搭配navigation进行使用


(1)创建一个导航条+容器:也就是我们上面案例种的左边部分(导航条)和内容显示部分(容器)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"android:layout_height="match_parent"><com.google.android.material.navigation.NavigationViewandroid:id="@+id/bnv_main_navigationbar"android:layout_width="300dp"android:layout_height="match_parent"android:background="@color/white"android:paddingHorizontal="9dp"app:itemBackground="@color/white"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:menu="@menu/backstage_menu_setting" /><androidx.fragment.app.FragmentContainerViewandroid:id="@+id/home_fragmentcontainerview"android:name="androidx.navigation.fragment.NavHostFragment"android:layout_width="0dp"android:layout_height="0dp"android:background="@drawable/dingdian_pic_background_sys"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="1.0"app:layout_constraintStart_toEndOf="@+id/bnv_main_navigationbar"app:layout_constraintTop_toBottomOf="@+id/backstage_constraintlayout"app:navGraph="@navigation/backstage_nav" /></androidx.constraintlayout.widget.ConstraintLayout>

(2)那么导航条view和容器view我们已经创建出来,那么导航条的这些:“首页”,“内容"这些item如何来呢?没错,可以看到上面我们使用了 app:menu=”@menu/backstage_menu_setting" ,我们需要创建meun对象出来。
在这里插入图片描述
在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:id="@+id/backstage_cottoncandyfragment"android:title="首页"/><itemandroid:id="@+id/backstage_paramsetfragment"android:title="内容"/><itemandroid:id="@+id/backstage_datastatfragment"android:title="咨讯"/><itemandroid:id="@+id/backstage_languagefragment"android:title="产品"/><itemandroid:id="@+id/backstage_errorstatfragment"android:title="图库"/><itemandroid:id="@+id/backstage_resetpwdfragment"android:title="消息"/><itemandroid:id="@+id/backstage_localalarmclockfragment"android:title="广告"/><itemandroid:id="@+id/backstage_permissionfragment"android:title="设置"/>
</menu>

(3)下面我们就需要创建fragment了,Fragment就是右边部分的容器内容。

@AndroidEntryPoint
class PriceFragment : BaseFragment<BackstageFragmentPriceBinding, ErrorStatFragmentVM>() {override val mViewModel: ErrorStatFragmentVM by viewModels()override fun createVB() = BackstageFragmentPriceBinding.inflate(layoutInflater)override fun BackstageFragmentPriceBinding.initView() {}override fun initObserve() {}override fun initRequestData() {mViewModel.getBanners()mViewModel.getArticleData()}}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/backstage_textview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Datastat"android:textSize="40dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

(4)那么如何设置点击这些“首页”,"资讯"就能打开对应的Fragment呢?使用Navigation,让我们可以使用非常简短的代码就能实现跳转。首先我们要创建一个导航文件
在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/backstage_nav"app:startDestination="@id/backstage_datastatfragment"><fragmentandroid:id="@+id/backstage_cottoncandyfragment"android:name="com.quyunshuo.wanandroid.home.ui.fragment.CottonCandyFragment"android:label="CottonCandyFragment" /><fragmentandroid:id="@+id/backstage_paramsetfragment"android:name="com.quyunshuo.wanandroid.home.ui.fragment.ParamSetFragment"android:label="ParamSetFragment" /><fragmentandroid:id="@+id/backstage_datastatfragment"android:name="com.quyunshuo.wanandroid.home.ui.fragment.DataStatFragment"android:label="DataStatFragment" /><fragmentandroid:id="@+id/backstage_errorstatfragment"android:name="com.quyunshuo.wanandroid.home.ui.fragment.ErrorStatFragment"android:label="ErrorStatFragment" /><fragmentandroid:id="@+id/backstage_languagefragment"android:name="com.quyunshuo.wanandroid.home.ui.fragment.LanguageFragment"android:label="LanguageFragment" /><fragmentandroid:id="@+id/backstage_resetpwdfragment"android:name="com.quyunshuo.wanandroid.home.ui.fragment.ResetPwdFragment"android:label="ResetPwdFragment" /><fragmentandroid:id="@+id/backstage_localalarmclockfragment"android:name="com.quyunshuo.wanandroid.home.ui.fragment.LocalAlarmClockFragment"android:label="LocalAlarmClockFragment" /><fragmentandroid:id="@+id/backstage_permissionfragment"android:name="com.quyunshuo.wanandroid.home.ui.fragment.PermissionFragment"android:label="PermissionFragment" /><fragmentandroid:id="@+id/backstage_otherfragment"android:name="com.quyunshuo.wanandroid.home.ui.fragment.OtherFragment"android:label="OtherFragment" />
</navigation>

注意,android:id="@+id/backstage_otherfragment"的id必须和menu的item id必须相同,这样才能找到对应的fragment
(5)实现使用navcontroller实现跳转

  bnvMainNavigationbar.setNavigationItemSelectedListener{val findNavController = findNavController(homeFragmentcontainerview.id)findNavController.navigate(it.itemId)true}

五、Fragment的生命周期


想要了解Fragment的生命周期,离不开Activity的生命周期,所以我们会一起讲到。

Fragment的生命周期由FragmentManager管理,FragmentManager负责将Fragment添加到Activity中,并在Fragment不再需要时将其移除。在Fragment的生命周期中,有几个关键点需要注意:

1)当Fragment被添加到Activity中时,会依次调用onAttach()、onCreate()、onCreateView()、onActivityCreated()、onStart()和onResume()方法。

2)当Fragment对用户不可见时(如被另一个Activity覆盖),会依次调用onPause()、onStop()方法。

3)当Fragment被移除或宿主Activity被销毁时,会依次调用onPause()、onStop()、onDestroyView()、onDestroy()和onDetach()方法。注意,如果只是Fragment被切换了,不会调用onDestroy()方法,只是调用onDestroyView,不要以为他离开了界面就是销毁了

在这里插入图片描述

5.1 Fragment的生命周期通过一系列回调方法来管理,这些方法在Fragment状态变化时被调用。以下是Fragment的主要生命周期回调方法:


1)onAttach(Context context):当Fragment与Activity关联时调用。这是Fragment生命周期中的第一个回调方法,此时可以获取到宿主Activity的引用。

2)onCreate(Bundle savedInstanceState):当Fragment被创建时调用。用于初始化Fragment的基本数据,如加载布局文件等。

3)onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState):创建Fragment的视图层次结构。如果Fragment没有UI,可以返回null。

4)onViewCreated(View view, Bundle savedInstanceState):当Fragment的视图被创建时调用。此时可以对视图进行进一步的初始化操作。

5)onActivityCreated(Bundle savedInstanceState):当宿主Activity的onCreate()方法完成后调用。此时Fragment的视图层次结构已完全创建,可以安全地与Activity的视图进行交互。

6)onStart():Fragment对用户可见时调用。此时Fragment开始对用户可见,但可能还未完全交互。

7)onResume():Fragment开始与用户交互时调用。此时Fragment完全可见且可交互。

8)onPause():Fragment失去焦点或停止与用户交互时调用。此时应保存一些重要数据或停止一些操作,如动画、网络请求等。

9)onStop():Fragment完全不可见时调用。此时应释放一些资源或做一些清理工作。

10)onDestroyView():Fragment的视图被销毁时调用。此时应释放与视图相关的资源。

11)onDestroy():Fragment被销毁时调用。此时应释放Fragment的成员变量和数据,以便回收内存和资源。

12)onDetach():Fragment与Activity分离时调用。此时应做一些最终的清理工作。

onDestroy和onDestroyView方法的区别

一、onDestroyView():
1)当Fragment的视图层次结构(即UI)被销毁时调用。这通常发生在Fragment不再需要显示其UI时,可能是因为用户离开了包含该Fragment的Activity,或者因为Fragment被替换或移除了。
2)在onDestroyView()被调用后,Fragment仍然存在于内存中,并且其状态(如成员变量等)仍然保持。但是,与视图相关的资源应该被释放,以避免内存泄漏。

二、onDestroy():
1)当Fragment被销毁时调用。这是Fragment生命周期中的最后一个回调方法,表示Fragment即将被系统回收,其资源将被完全释放。
2)在onDestroy()被调用后,Fragment无法再接收到任何生命周期回调,并且其资源(如内存)将被系统回收。


onDestroyView()主要负责释放与视图相关的资源,而onDestroy()则负责清理Fragment占用的所有资源。

六、Android开发,建议是多个activity,还是activity结合fragment,原因是什么


主要取决于你的应用需求、设计目标以及用户体验的考虑。下面是一些关于这两种方式的优缺点以及选择建议:
1. 使用多个Activity

优点:

清晰的逻辑分离:每个Activity可以专注于一个特定的任务或用户流程,使得代码更加模块化和易于管理。
任务栈管理:Android系统通过任务栈管理Activity,可以很方便地实现页面之间的跳转和返回,尤其是在处理复杂的用户流程时。
内存管理:当Activity不再需要时,系统可以更容易地回收其占用的资源。

缺点:

    界面切换动画:Activity之间的切换可能会比Fragment之间的切换更重,因为涉及到整个界面的重建。数据共享:Activity之间的数据共享可能需要通过Intent、全局变量或数据库等方式,相对复杂。用户体验:在某些情况下,过多的Activity跳转可能会导致用户感到困惑,尤其是在需要频繁切换界面时。

2.使用Activity结合Fragment

优点:

 灵活的界面布局:Fragment可以在一个Activity中重用,并且可以在运行时动态地添加、移除或替换,非常适合实现复杂的用户界面布局。更好的用户体验:Fragment之间的切换通常比Activity之间的切换更流畅,因为不需要重建整个界面。数据共享:Fragment与宿主Activity之间的数据共享更加直接和方便,可以通过接口回调等方式实现。缺点:
```kt复杂性增加:Fragment的生命周期比Activity更复杂,需要更仔细地管理,以避免内存泄漏等问题。状态管理:Fragment的状态管理可能更加复杂,尤其是在处理多个Fragment的嵌套和动态变化时。

选择建议

    如果你的应用界面相对简单,且每个界面之间的逻辑相对独立,可以考虑使用多个Activity。如果你的应用需要实现复杂的用户界面布局,或者需要在同一个Activity中动态地展示不同的内容区域,那么使用Activity结合Fragment可能是一个更好的选择。考虑用户体验和内存管理。Fragment之间的切换通常更流畅,但也需要更仔细地管理其生命周期和状态。考虑应用的维护性和可扩展性。使用Fragment可以使代码更加模块化和可重用,但也可能增加复杂性。

七、返回键如何处理

在activity中,我们导航了很多的Fragment,比如从A Framgent到了B Fragment,再到了C Fragment,如果我想点击物理的返回按键,如何返回到到一个Fragment呢?并且,如果到了最初的A Framgnet,想提示如果再次点击将退出app这种的提示应该如何写呢?

 override fun onBackPressed() {val navController =findNavController(mBinding.homeFragmentcontainerview.id)val fragmentPopped = navController.popBackStack()Log.d("fragmentPopped", "onBackPressed: "+fragmentPopped)// 如果popBackStack()返回false,意味着没有Fragment可以返回了// 这里你可以假设已经回到了最开始的Fragment,或者根本就没有Fragment在栈中if (!fragmentPopped) {// 没有任何Fragment可以返回了,结束Activity// 获取当前时间戳val currentTime = System.currentTimeMillis()// 判断与上一次点击返回键的时间间隔是否小于1秒if (currentTime - backPressedTime < 1000) {super.onBackPressed() // 执行默认的返回键操作(退出Activity)} else {Toast.makeText(this, "再次点击返回键退出", Toast.LENGTH_SHORT).show()backPressedTime = currentTime // 更新上一次点击返回键的时间戳}}}

navController.popBackStack()会移除栈顶的Fragment,如果存在fragment,就会返回true,否则返回false。

7.1 假如说,我想从A Fragment跳到B Fragment的时候,我想A Fragment直接就销毁了呢?

  <fragmentandroid:id="@+id/home_homefragment"android:name="com.quyunshuo.wanandroid.home.ui.fragment.HomeFragment"android:label="HomeFragment" ><actionandroid:id="@+id/home_action_home_homefragment_to_home_makefragment"app:destination="@id/home_makefragment"app:popUpTo="@id/home_homefragment"app:popUpToInclusive="true"/><fragment/>

app:popUpTo=“@id/home_homefragment”
app:popUpToInclusive=“true”
的意思就是跳转的时候,将之前的Fragment销毁掉。就保留自己作为栈顶

八、Navigation搭配Fragment使用后,事务是怎么样?

当使用Navigation组件来管理Fragment的创建和切换时,Fragment的事务(Transaction)是通过Navigation图(Navigation Graph)和NavController来隐式处理的。这种方式简化了Fragment的切换逻辑,让开发者可以更专注于Fragment之间的交互和业务逻辑的实现。

Fragment事务的隐式处理

1)在传统的Fragment管理中,你可能需要显式地调用FragmentManager的beginTransaction()、add()、replace()等方法来创建Fragment事务。但在使用Navigation组件时,这些操作都被封装在Navigation图内,并由NavController根据导航操作(如点击按钮、接收通知等)来自动处理。

2)例如,当你在Navigation图中定义了两个Fragment(A和B),并从一个Fragment(A)到另一个(B)的导航时,你只需要在A Fragment中调用NavController的navigate()方法,并传入目标Fragment的ID或Action ID。NavController会根据Navigation图自动处理Fragment的添加、替换和移除等事务。

https://blog.csdn.net/weixin_36049771/article/details/117580874?ops_request_misc=&request_id=&biz_id=102&utm_term=Fragment%E7%9A%84%E4%BB%BB%E5%8A%A1%E6%A0%88&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-3-117580874.142v100pc_search_result_base4&spm=1018.2226.3001.4187

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Java开发笔记--通用基础数据校验的设计
  • 思科CCIE最新考证流程
  • 工业三防平板助力MES系统打造工厂移动式生产管理
  • 视频编辑与制作软件哪个好 会声会影视频制作教程 会声会影软件下载免费中文版
  • 结构开发笔记(二):solidworks软件(一):介绍、下载和安装过程
  • JVM内存模型笔记
  • Print 前端打印 (调用 windows 自带打印功能,打印指定 dom 元素内容)
  • 【机器学习算法基础】(基础机器学习课程)-11-k-means-笔记
  • 3.OpenFeign与负载均衡
  • “碳”为观止,奥运会也“卷”起来了
  • 虚拟电厂,GPS北斗卫星同步时钟守护智慧能源
  • API 接口设计原则:RESTful 与 GraphQL
  • Golang | Leetcode Golang题解之第321题拼接最大数
  • RemCom和impacket.psexec简介
  • 【计算机网络---OSI七层模型】
  • angular组件开发
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • EventListener原理
  • Js基础知识(四) - js运行原理与机制
  • Linux快速复制或删除大量小文件
  • mysql中InnoDB引擎中页的概念
  • Python socket服务器端、客户端传送信息
  • React-Native - 收藏集 - 掘金
  • STAR法则
  • underscore源码剖析之整体架构
  • vuex 笔记整理
  • 从setTimeout-setInterval看JS线程
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 全栈开发——Linux
  • 如何编写一个可升级的智能合约
  • 如何设计一个比特币钱包服务
  • 使用docker-compose进行多节点部署
  • 微信小程序--------语音识别(前端自己也能玩)
  • 我感觉这是史上最牛的防sql注入方法类
  • ​Java并发新构件之Exchanger
  • ​queue --- 一个同步的队列类​
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • (libusb) usb口自动刷新
  • (Note)C++中的继承方式
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (九)信息融合方式简介
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (转)一些感悟
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • .NET : 在VS2008中计算代码度量值
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • // an array of int
  • [ Algorithm ] N次方算法 N Square 动态规划解决
  • [1204 寻找子串位置] 解题报告
  • [16/N]论得趣
  • [Android] Android ActivityManager
  • [Angular] 笔记 20:NgContent