fragment常用知识点

news2024/11/19 5:31:20

fragment基本使用

摘自官网的代码示例

class ExampleActivity : AppCompatActivity(R.layout.example_activity) {
      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 注意这里有判断,当saveInstanceState为空时再创建。 表示activity不是重建的,防止fragment重复创建。 
        if (savedInstanceState == null) {
            val bundle = bundleOf("some_int" to 0)
            supportFragmentManager.commit {
                setReorderingAllowed(true)
                // 在add方法中通过bundle传递参数。 貌似是高版本的用法,在源码中没有看到。 
                add<ExampleFragment>(R.id.fragment_container_view, args = bundle)
            } 
        }
    }
}
class ExampleFragment : Fragment(R.layout.example_fragment) {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // 通过requireArguments方法获取参数。 
        val someInt = requireArguments().getInt("some_int") 
        ...
    }
}

其中,requireArguments方法如下,主要是对传参进行了一个校验。
requireArguments

如果没有调用setArgument传参,调用requireArguments方法就会报错。

setArgument
从方法说明中可知,该方法要在添加之前调用。

回退栈

在添加fragment的同时加入回退栈,

supportFragmentManager.beginTransaction()
    .replace(R.id.fragment_container, fragment)
    .addToBackStack("hello")   // 只有加了回退栈,才可以结合popbackstack来实现回退处理。
    .commit()

需要注意的是,fragment加入回退栈时不能使用commitNow及commitNowAllowingStateLoss提交。
主要是在这两个方法中有disallowAddToBackStack()方法检测是否已经加入回退栈了,如果加入了那么会抛出IllegalStateException异常。

commitNowAllowingStateLoss
disallowAddToBackStack

如下代码可以监听回退栈的数据变化。

supportFragmentManager?.addOnBackStackChangedListener {
    // 回退栈变化监听,系统接口提供了反注册,注意销毁时反注册
    Log.i(TAG, "onCreate: 回退栈 size : ${supportFragmentManager.backStackEntryCount}")
    val size = supportFragmentManager.backStackEntryCount
    for (i in 0 until size) {
        val backstackEntry = supportFragmentManager.getBackStackEntryAt(i)
        Log.i(TAG, "第${i}个回退栈元素信息: $backstackEntry, name is ${backstackEntry.name}")
    }
}

通过如下代码在activity的某个布局id中添加三个fragment
demo

监听器中会打印如下日志

第0个回退栈元素信息: BackStackEntry{6145541 #0 hello}, name is hello
第1个回退栈元素信息: BackStackEntry{8099e32 #1 1}, name is 1
第2个回退栈元素信息: BackStackEntry{d274363 #2 2}, name is 2
第3个回退栈元素信息: BackStackEntry{326b9c0 #3 3}, name is 3

在FragmentManager中提供了popBackStack()和popBackStack(name, flag)两个方法。

popBackStack()是将栈顶的BackStackEntry弹出栈,在上面的场景中,当前的界面是fragment3,如果调用一次,界面会显示fragment2.

popBackStack(name, flag)方法会通过name找到对应的BackStackEntry对象,然后根据flag的值决定如何弹出。

flag取值有0和FragmentManager.POP_BACK_STATE_INCLUSIVE(该常量值为1)。

在上面的场景中,如果name传2,flag传0,那么会找到BackStackEntry{d274363 #2 2}对象,flag为0表示将当前这个BackStackEntry对象保留在回退栈中,那么此时,只会将fragment3出栈,界面显示fragment2.

如果name传2 ,flag传1也即是FragmentManager.POP_BACK_STATE_INCLUSIVE,表示将name对应的BackStackEntry一同出栈。此时,回退栈中只会保留fragment1.

注意,如果通过name没有找到对应的BackStackEntry对应,那么该方法不会出栈任何元素,回退栈也不会有变化。

返回逻辑

常见的返回处理逻辑如下:

override fun onBackPressed() {
    supportFragmentManager.let {
        // 回退栈有内容时才处理fragment回退
        if (it.backStackEntryCount > 0) {
            Log.i(TAG, "onBackPressed: supportFragmentManager.popBackStack() execute")
            // 根据业务需要选择弹出方式
            it.popBackStack()
//                it.popBackStack("hello", 0) // 如果栈中没有对应name的backstackEntry,那么不会有任何响应
//                it.popBackStack("hello", FragmentManager.POP_BACK_STACK_INCLUSIVE)
        } else {
            Log.i(TAG, "onBackPressed: default")
            super.onBackPressed()
        }
    }
}

事务的提交方式

在FragmentTransaction中提供了四种提交方式,分别为commit、comimitNow、commitAllowingStateLoss、commitNowAllowingStateLoss。

下面是commit方法的说明

Schedules a commit of this transaction. The commit does
not happen immediately; it will be scheduled as work on the main thread
to be done the next time that thread is ready.

A transaction can only be committed with this method
prior to its containing activity saving its state
. If the commit is
attempted after that point, an exception will be thrown. This is
because the state after the commit can be lost if the activity needs to
be restored from its state. See {@link #commitAllowingStateLoss()} for
situations where it may be okay to lose the commit.

@return Returns the identifier of this transaction’s back stack entry,
if {@link #addToBackStack(String)} had been called. Otherwise, returns
a negative number.

public abstract int commit();

这段说明有两个重点, 一是提交是异步的,二是事务必要要在activity保存状态前提交。

这个规定是为了确保在 Activity 生命周期过程中的正确性。Activity 在销毁和重新创建时,会保存和还原其状态。如果在状态保存之后修改了 FragmentTransaction,系统可能无法正确还原 Fragment 的状态,因此在这个时候进行提交会导致异常。这是 Android 系统为了确保应用的稳定性而设置的一种保护机制。在需要提交事务的时候,通常应该在 Activity 生命周期的早期进行。

有了对commit的理解就很好理解commitAllowingStateLoss方法了,该方法允许丢失Fragment状态,故也没有强制必须要在activity保存状态前提交,相当于提交的时机没有那么多的限制。
so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.
这两个方法在源码上区别也不大,只是多了对activity保存状态的检测。 具体如下图
在这里插入图片描述
enqueueAction
schedulecommit

通过上述源码可知,commit及commitAllowingStateLoss是通过Handler将添加逻辑post到主线程执行的。
而commitNow及commitNowAllowingStateLoss是立即执行的。

post执行与立即执行具体有啥区别呢?

使用 commitNow 方法时,该事务会立即执行。这意味着直到该事务执行完毕,你的代码会被阻塞。这样可以确保在调用 commitNow 后,你可以立即访问新的 Fragment 状态。

适用情况:

  • 当你需要立即执行 FragmentTransaction 并确保立即生效时。
  • 当你不希望将事务添加到主线程的消息队列中。

其他情况则推荐使用commit方法。

提交方式是否异步是否允许丢失状态
commit
commitAllowingStateLoss
commitNow
commitNowAllowingStateLoss

状态保存

fragment与activity相同,提供了onSaveInstance回调方法来保存相关状态。
具体用法如下:

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putBoolean(IS_EDITING_KEY, isEditing)
    outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed)
}
// 在onCreate方法中读取保存的数据。 
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    isEditing = savedInstanceState?.getBoolean(IS_EDITING_KEY, false)
    randomGoodDeed = savedInstanceState?.getString(RANDOM_GOOD_DEED_KEY)
            ?: viewModel.generateRandomGoodDeed()
}

view state的保存与恢复
如果view没有id,那么系统是不会对该view的状态进行保存的。其实也很好理解,如果没有id,那么一般也不会动态修改该view的属性了,故也没有太大的必要保存该view的状态。

父子关系的FragmentManager

Fragments can host one or more child fragments. Inside a fragment, you can get a reference to the FragmentManager that manages the fragment’s children through getChildFragmentManager(). If you need to access its host FragmentManager, you can use getParentFragmentManager().

注意,在有父子fragment嵌套的地方,使用FragmentManager时一定要注意,否则可能会crash。

下图摘自官网介绍。
image.png

参考

1、官网
2、fragment saving-state
3、FragmentManager

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1302582.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

git提交代码报错Git: husky > pre-commit

目录 git提交代码报错原因解决方法&#xff08;三种&#xff09;1、第一种2、第二种3、第三种 git提交代码报错原因 这个问题是因为当你在终端输入git commit -m “XXX”,提交代码的时候,pre-commit(客户端)钩子&#xff0c;它会在Git键入提交信息前运行做代码风格检查。如果代…

53 代码审计-TP5框架及无框架变量覆盖反序列化

目录 演示案例:Metinfo-无框架-变量覆盖-自动审计或搜索phpmyadmin-无框架-反序列化-自动审计或搜索Thinkphp5-有框架-搭建使用入口访问调试SQL等 演示案例: Metinfo-无框架-变量覆盖-自动审计或搜索 变量覆盖会直接覆盖原始变量&#xff0c;来形成新的变量值 搜索关键字或者…

智慧社区前景无限,科技引领未来发展

社区是城镇化发展的标志&#xff0c;作为人类现代社会的生活的基本圈子&#xff0c;是人类生活离不开的地方&#xff0c;社区人口密度大、车辆多&#xff0c;管理无序&#xff0c;社区的膨胀式发展多多少少带来一定的管理上的缺失。社区作为智慧城市建设的重要一环&#xff0c;…

zedbox 实现配置 yolov5

Stereolabs 的 ZED Box 是一款由 NVIDIA Jetson™ 提供支持的紧凑型网关&#xff0c;用于在移动和现场情况下挑战 AIoT&#xff08;物联网&#xff09;。它旨在将空间感知和理解带到边缘&#xff0c;并聚合、处理和分析来自 3D 传感器和设备的数据。 相关内容 1.win10下 cud…

A-23 P离子交换树脂:高效去除无机有机污染物的新选择

在当今水处理行业中&#xff0c;高效、环保的离子交换树脂备受关注。本文将为您介绍一款具有卓越性能的碱性季胺基阴离子交换树脂——Tulsion A-23 P。通过分析其特性和应用&#xff0c;展示其在水处理领域的优势。 一、Tulsion A-23 P离子交换树脂的特性 物理化学稳定性&#…

Connection refused: no further information

解决目录 一、报错信息二、解决方法 一、报错信息 二、解决方法 1、报错原因是开启了代理&#xff0c;像AS是绝对不能开代理的。 2、设置为No proxy&#xff0c;然后Apply再选择OK&#xff0c;重新同步。 要远离消耗你的人和事&#xff0c;不要花费任何情绪或者精力在他们身…

【排序算法】快速排序

一&#xff1a;基本概念 1.1 介绍 快速排序由C. A. R. Hoare在1962年提出&#xff0c;它是一种基于二叉树结构的交换排序算法&#xff0c;它采用了一种分治的策略&#xff0c;通常称其为分治法。该方法的基本思想是&#xff1a;先从数列中取出一个数作为基准数&#xff0c;然…

【MySQL系列】Centos安装MySQL

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

10天玩转Python第1天:python基础知识与常用开发工具全面详解

这里写自定义目录标题 1.课程之前1.1 课程介绍1.2 今日内容1.3 Python 介绍[了解]1.4 语言的分类 2 Python 环境配置2.1 Python 解释器的安装2.2 pycharm 的配置安装2.3 路径的选择(建议) 3 使用 pycharm 书写代码3.1 双击打开 pycharm 软件3.2 创建新 项目3.3 配置项目的路径和…

网工内推 | 项目经理专场,最高20K*13薪,软考证书优先

01 Trasen 招聘岗位&#xff1a;大项目经理&#xff08;医疗行业/HIS&#xff09; 职责描述&#xff1a; 1.负责项目按计划完成交付并顺利验收结项&#xff1b; 2.参与项目前期预算、评审、方案设计等&#xff1b; 3.负责具体项目实施&#xff0c;制定项目计划、组织项目资源、…

wvp gb28181 pro 配置https访问

准备工作 必须要有域名。虽然数字证书也有ip证书,但是会很麻烦,多数ca机构验证服务器需要用到80或443端口,也就是必须先备案,所以最好还是使用域名证书。购买域名证书。根据安全级别要求自行配置。单域名(不支持通配符的),阿里云的域名都是可以免费申请的。完成域名到服…

jieba,一个结巴的Python库

微信公众号&#xff1a;愤怒的it男&#xff0c;超多Python技术干货文章。 一、jieba的简介 在自然语言处理任务时&#xff0c;中文文本需要通过分词获得单个的词语&#xff0c;此时一个好的分词工具是非常有必要的。jieba分词是一个开源项目&#xff0c;地址为&#xff1a;git…

Python从入门到精通四:Python循环语句

前言 循环普遍存在于日常生活中&#xff0c;同样&#xff0c;在程序中&#xff0c;循环功能也是至关重要的基础功能。 为什么学习循环语句 循环在程序中同判断一样&#xff0c;也是广泛存在的&#xff0c;是非常多功能实现的基础&#xff1a; while循环的基础语法 学习目标&…

竞赛保研 LSTM的预测算法 - 股票预测 天气预测 房价预测

0 简介 今天学长向大家介绍LSTM基础 基于LSTM的预测算法 - 股票预测 天气预测 房价预测 这是一个较为新颖的竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/postgraduate 1 基于 Ke…

基于Qt的登录页面设计

题目&#xff1a; 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和…

leetcode 股票DP系列 总结篇

121. 买卖股票的最佳时机 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。 只能进行一次交易 很简单&#xff0c;只需边遍历边记录最小值即可。 class Solution { public:int maxProfit(vector<int>& prices) {int res …

Java:字符流 文件输出 与 读入 方法

Java&#xff1a;字节流 文件输出与读入方法 并 实现文件拷贝 文章目录 字符流FileReaderFileWrite 字符流 字符流底层就是字节流。 字符流 字节流 字符集 特点&#xff1a; 输入流&#xff1a;一次读入一个字节&#xff0c;遇到中文时&#xff0c;一次读多个字节。 输出流…

我的 CSDN 三周年创作纪念日:2020-12-12

本人大叔一枚&#xff0c;自1992年接触电脑&#xff0c;持续了30年的业余电脑发烧爱好者&#xff0c;2022年CSDN博客之星Top58&#xff0c;阿里云社区“乘风者计划”专家博主。自某不知名财校毕业后进入国有大行工作至今&#xff0c;先后任职于某分行信息科技部、电子银行部、金…

六级翻译之印章

好像大房子挺难得 三段式 1Since ancient from now&#xff0c;seals have been a symbol of power and certerfiction of identity.seals not only practical but also is a form of art.Seal is an ancient art combining with manafutuer of crafting and desgin of…

基于SSM的健身房预约系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…