草庐IT

java - popBackStack() 和 replace() 操作有何不同?

coder 2023-05-17 原文

在管理 Fragments 时,我在我的应用程序中遇到了一些奇怪的行为,我想知道 SO 是否可以帮助阐明为什么会发生这种情况。

我有两个 Fragment,我们称它们为 Fragment A 和 Fragment B。我的应用程序的一般流程是,当用户以某种方式与 Fragment A 交互时,通过调用 fragmentTransaction.replace 显示 Fragment B () (这在所有情况下都会发生)。当我显示 Fragment B 时,我将 Fragment A 添加到后堆栈;然后,当用户按下 Fragment B 上的返回按钮时,Fragment A 通过从返回堆栈中弹出来再次显示。

这一切都很好,但是今天我发现有一个来自 Fragment B 的流调用 fragmentTransaction.replace(),将 Fragment B 替换为当前正在运行的 Fragment A 的相同实例后栈。

这本身并没有什么问题,但是当我从 fragment A 回到 fragment B 时会出现奇怪的行为。如果我调用 fragmentTransaction.replace()onCreate fragment B 的 () 方法没有被调用。

但是,如果我从后面的堆栈中弹出 Fragment A,然后用 Fragment B 替换它,则会触发 Fragment B 的 onCreate() 方法。这是为什么呢?

请注意,Fragment A 和 Fragment B 的所有实例都是在其宿主 Activity 启动时创建的。

为澄清而编辑。第二次调用 onCreate() 的情况如下:附加 Fragment A => 用 Fragment B 替换,将 Fragment A 添加到后端堆栈 => 使用 popBackStack( ) => 再次用 Fragment B 替换 Fragment A。

最佳答案

replace() 做了两件事:

  1. 从您指定的容器 (C) 中移除当前添加的 fragment (A)
  2. 将新 fragment (B) 添加到同一容器中

这两个操作被保存为 Backstack 记录/事务。请注意, fragment A 仍处于 created 状态,并且其 View 已被销毁。

现在 popBackStack() 会反转您添加到 BackStack 的最后一个事务。

在这种情况下,这将是 2 个步骤:

  1. 从 C 中删除 B
  2. 将 A 添加到 C

在此之后, fragment B 变为 分离,如果您不保留对它的引用,它将被垃圾回收。

要回答您问题的第一部分,没有 onCreate() 调用,因为 FragmentB 仍处于 created 状态。问题的第二部分的答案更长一些。

首先,重要的是要了解您实际上并没有将 Fragments 添加到 Backstack,而是添加了 FragmentTransactions。因此,当您认为“用 fragment B 替换,将 fragment A 添加到后台堆栈”时,您实际上将整个操作添加到后台堆栈 - 即 用 B 替换 A。这个替换包括 2操作 - 删除 A 并添加 B。

然后,下一步是弹出包含此替换的事务。所以你不是在弹出 FragmentA,你是在反转“删除 A,添加 B”,反转是“删除 B,添加 A”。

然后最后一步应该更清楚 - FragmentManager 不知道 B,所以当你在最后一步通过用 B 替换 A 来添加它时,B 需要通过它的早期生命周期方法 - onAttach( )onCreate().

下面的代码说明了正在发生的事情。

FragmentManager fm  = getFragmentManager();
FragmentA fragmentA = new FragmentA();
FragmentB fragmentB = new FragmentB();

// 1. Show A
fm.beginTransaction()
  .add(fragmentA, R.id.container)
  .commit();

// 2. Replace A with B
// FragmentManager keeps reference to fragmentA;
// it stays attached and created; fragmentB goes 
// through lifecycle methods onAttach(), onCreate()
// and so on.
fm.beginTransaction()
  .replace(fragmentB, R.id.container)
  .addToBackstack(null)
  .commit();

// 2'. Alternative to replace() method
fm.beginTransaction()
  .remove(fragmentA)
  .add(fragmentB, R.id.container)
  .addToBackstack(null)
  .commit();

// 3. Reverse (2); Result - A is visible
// What happens:
//   1) fragmentB is removed from container, it is detached now;
//      FragmentManager doesn't keep reference to it anymore
//   2) Instance of FragmentA is placed back in the container
// Now your Backstack is empty, FragmentManager is aware only
// of FragmentA instance
fm.popBackStack();

// 4. Show B
// Since fragmentB was detached, it goes through its early
// lifecycle methods: onAttach() and onCreate().
fm.beginTransaction()
  .replace(fragmentB, R.id.container)
  .addToBackstack(null)
  .commit();

关于java - popBackStack() 和 replace() 操作有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17793249/

有关java - popBackStack() 和 replace() 操作有何不同?的更多相关文章

  1. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  2. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  3. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  4. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  5. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  6. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  7. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  8. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

    我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

  9. java - Ruby 相当于 Java 的 Collections.unmodifiableList 和 Collections.unmodifiableMap - 2

    Java的Collections.unmodifiableList和Collections.unmodifiableMap在Ruby标准API中是否有等价物? 最佳答案 使用freeze应用程序接口(interface):Preventsfurthermodificationstoobj.ARuntimeErrorwillberaisedifmodificationisattempted.Thereisnowaytounfreezeafrozenobject.SeealsoObject#frozen?.Thismethodretur

  10. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

随机推荐