刷新片段不再起作用了?

12

今天我浪费了一些时间,因为我的代码不再起作用了。在更新至新版Support Library 25.1.0后,重新加载片段视图的代码不再起作用:

这是我的代码:

FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = manager.beginTransaction();
fragmentTransaction.detach(fragment);
fragmentTransaction.attach(fragment);
fragmentTransaction.commit();

我尝试调试并设置了一些断点

public void onPause()
public void onStop()
public void onAttach(Context context)
public void onDetach()  
public void onDestroyView()
public void onDestroy()

但是应用程序没有进入任何那个函数,屏幕上也没有发生任何事情。

如果我单独调用detach而没有调用attach,应用程序会进入onPause和onStop,并且视图会离开屏幕。


1
你应该将这个问题分成两部分,然后回答自己的问题。不要把问题和答案放在一起,这会让人感到困惑。 - Rick S
谢谢!过一段时间后,您应该能够将其标记为被接受的答案。 - Rick S
@AidaIsay:不,我只是回退到库支持版本25.0.1。 - Brahim Bouaboud
5个回答

18

在将androidx.navigation从2.3.1更新到2.3.2后,遇到了类似的问题。

parentFragmentManager.beginTransaction().detach(this).attach(this).commit()

已停止重新加载碎片的视图。 我在这里找到的所有内容都没有帮助,但我注意到分离和附加操作单独执行时成功,我决定将它们的执行分散到不同的FragmentTransaction实体中:

parentFragmentManager.beginTransaction().detach(this).commit ()
parentFragmentManager.beginTransaction().attach(this).commit ()

它有效了。 希望这能节省某些人的时间。


2
除了这个解决方案,其他的都对我没用。真正节省了我的时间。非常感谢。 - Prantik Mondal

9

我曾遇到同样的问题,但在网上找不到答案。最终我发现,在支持库的25.1.1版本中添加了一些Fragment Transactions优化(请参见https://developer.android.com/topic/libraries/support-library/revisions.html#25-1-1)。禁用这些优化可使您的事务按预期工作:

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setAllowOptimization(false);
transaction.detach(fragment).attach(fragment).commitAllowingStateLoss();

更新

setAllowOptimization已被弃用,请使用setReorderingAllowed代替。


2
{btsdaf} - Aba

6

@Viad已经回答了这个问题。再补充一点,这种情况发生在Android版本26及以上,默认情况下允许重新排序。当两个片段操作同时请求时,例如添加片段1然后用片段2替换它,这会导致只有后者(替换片段2)发生。

因此,当默认情况下允许重新排序时,使用detach(fragment).attach(fragment)重新启动片段时,第一个将被忽略,只执行第二个。由于片段已经附加,attach(fragment)不会执行任何操作。这就是为什么片段的任何生命周期方法都没有被调用。

解决该问题的方法是使用setReorderingAllowed(false)来停用重新排序。因此,解决方案如下:

                    FragmentTransaction transaction = mActivity.getFragmentManager()
                            .beginTransaction();
                    if (Build.VERSION.SDK_INT >= 26) {
                        transaction.setReorderingAllowed(false);
                    }
                    transaction.detach(fragment).attach
                            (fragment).commit();

SDK 版本大于 25 的问题让我疯了,谢谢! - Marcel Hofgesang

2
要使用Androidx实现片段的刷新有点不同。
根据Android开发者文档这里

由于FragmentTransaction被视为一组原子操作,同一事务中对同一片段实例进行detach和attach的调用会相互取消,从而避免了片段UI的销毁和立即重建。如果要分离然后立即重新附加片段,请使用单独的事务,并在使用commit()时通过executePendingOperations()进行分隔。

因此,代码必须像这样:
fun FragmentActivity.relaunchFragment(fragmentId: Int) {
    val currentFragment = supportFragmentManager.findFragmentById(fragmentId)
    val detachTransaction = supportFragmentManager.beginTransaction()
    val attachTransaction = supportFragmentManager.beginTransaction()

    currentFragment?.let {
        detachTransaction.detach(it)
        attachTransaction.attach(it)
        detachTransaction.commit()
        attachTransaction.commit()
    }
}

executePendingOperations是什么?你的代码中没有executePendingOperations - 4rigener

2

这是我对代码进行的轻微修改,使用了 getSupportFragmentManager

FragmentTransaction t = getActivity().getSupportFragmentManager().beginTransaction();
t.setAllowOptimization(false);
t.detach(this).attach(this).commitAllowingStateLoss();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接