刷新常量片段

Refreshing For Constant Fragments

我会尽量描述问题并简化它 在我的应用程序中,我有一个 activity 和 3 个片段,我在 Phone 模式下交换它们。这些片段我将它们的片段实例作为 main activity 中的常量对象,因此与片段生命周期无关的内部对象保持它们的值,即使这个片段不可见(逻辑上对象将在片段时释放对象被销毁)

现在,当我尝试让我的应用程序支持平板电脑时,我同时显示了 3 个片段,但发生了一些奇怪的事情。

假设片段 A 包含项目列表,片段 B 显示 selected 项目的详细信息。片段 B 处有一个对象。此对象保存 selected 项目 ID [所有片段同时显示在一个 activity 中,如前所述],此对象保存当前项目 ID 值时片段 B 创建,并在片段 B 调用 onDestroyView() 方法时保存新的 selected 项目 ID。

现在,当我启动我的应用程序时,我添加片段 A,当我从列表中添加 select 项时,片段 B 被添加并且其对象持有 selected 值。现在一切都很好。 当我 select 另一个项目时,我只需要刷新片段 B 因为内部对象将保存新的 selected id 所以我做了这一行

 Fragment fragment = mFragmentManager.findFragmentByTag([fragmentId]);
 mFragmentManager.beginTransaction().detach(fragment).attach(fragment).commit();

但我得到的结果是片段 B 获得了它之前的状态,我的意思是内部对象持有第一个项目 ID i selected.

我尝试在片段刷新前测试内部对象

 Fragment fragment = mFragmentManager.findFragmentByTag([fragmentId]);
 Log.e("my object","value" + String.valueOf(fragment.getValue));
 mFragmentManager.beginTransaction().detach(fragment).attach(fragment).commit();

并且它持有必须显示的正确项目 ID 值...!! 我也传递了常量值来确保但我得到了同样奇怪的结果

 Fragment fragment = mFragmentManager.findFragmentByTag([fragmentId]);
 mFragmentManager.beginTransaction().detach(fragment).attach(FRAGMENT).commit();

所以发生了什么?? 逻辑上它必须像我想的那样工作。

图片为原码 这是日志结果(注意:2 是我 selected 的下一项) 这是刷新片段 B 后的下一个日志结果(注意片段 B 中的此日志,id 3 是第一个项目 i selected)预期结果是 2

我终于理解了片段事务行为及其工作原理...

一旦你 add/replace 新片段到 Fragment Transaction 你的对象被保存为 Fragment Manager 中的初始状态并且当你尝试分离片段并重新附加 [同一对象] Fragment Manager 将获取您之前传递给 add()/replace() 函数的对象状态。 这就是我得到结果的原因。

为了简化它。

  • 假设你有一个 Class A extends from Fragment class 并且这个 class contains Integer object have no value并有 Set()/Get() 方法。

  • 现在从这个 Class A 创建一个实例并调用 Set() 函数并将值 1 传递给它。然后通过 add()/replace()` 方法将此实例传递给 Manager Transaction

  • 现在尝试调用 Set() 函数并将 Integer 对象更改为另一个值。

  • 分离 class A 并重新附加它并检查此对象的值,您将得到对象 return 的值到您在传递之前分配的初始值反对 Manger Transaction

除此之外还有一个重要说明... Fragment Transaction add()replace()remove() ... 等操作在主线程中不起作用,这就是使用 commit() 方法和 commitNow() 方法 .. 因为当您使用 commit() 时,您的操作将添加到 Fragment Transaction 队列中,因此它会在一段时间后执行,但不是现在根据其在队列中的顺序,这样您就有了另一个名为 commitNow() 的方法来使您的操作立即执行。