【问题标题】:Refreshing For Constant Fragments刷新恒定片段
【发布时间】:2018-09-17 20:54:51
【问题描述】:

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

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

说片段 A 保存项目列表,片段 B 显示所选项目的详细信息。并且在fragment B处有一个对象,这个对象保存了选中的item id [所有fragment同时显示在一个activity中,正如我之前提到的],这个对象在fragment B创建时保存当前item id值,并保存新的在片段 B 处调用 onDestroyView() 方法时选择的项目 ID。

现在,当我启动我的应用程序时,我添加了片段 A,当我从列表中选择项目时,添加了片段 B,并且它的对象保存了选定的值。现在所有的事情都是正确的。 当我选择另一个项目时,我只需要刷新片段 B,因为内部对象将保存新选择的 id,所以我做了这一行

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

但是我得到的结果是片段 B 获得了它之前的状态,我的意思是内部对象保存了我选择的第一个项目 id。

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

 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 是我选择的下一项) 这是刷新片段 B 后的下一个日志结果(注意片段 B 中的这个日志,id 3 是我选择的第一个项目)预期结果是 2

【问题讨论】:

    标签: android oop android-fragments android-inflate


    【解决方案1】:

    终于明白了片段事务的行为以及它是如何工作的……

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

    为了简化它。

    • 假设您有一个从 Fragment 类扩展而来的 A 类,并且该类包含 Integer 对象,没有任何值并且具有 Set()/Get() 方法。

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

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

    • 分离A类并重新附加它并检查该对象的值,您会发现对象的值返回到您在将对象传递给Manger Transaction之前分配的初始值

    除此之外还有一个重要的注意事项...Fragment Transactionadd()replace()remove() ... 等操作在主线程中不起作用,这就是使用commit() 方法和commitNow() 方法的原因.. 因为当您使用commit() 时,您的操作将添加到Fragment Transaction 队列中,因此它将在一段时间后执行,但现在不是按照队列中的顺序执行,因此您有另一种方法称为commitNow()让您的操作立即执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多