片段事务加载空视图,但在旋转设备后仍显示片段

11
我正在按照Google文档设计的方式构建一个导航抽屉,但我遇到了一个问题,即Fragment没有被替换。应用首次加载时会加载默认的Fragment。单击抽屉列表上的其他项会留下空视图。但是在旋转设备后,将加载所选的Fragment。http://developer.android.com/training/implementing-navigation/nav-drawer.html
public void selectNavActivty(int position){
    // TODO Changing between the different screens selection
    fragment = null;
    switch (position) {
        case 0:
            fragment = OverLay.newInstance();
            break;
        case 1: 
            fragment = Dummy.newInstance();
            break;
        }

    if(fragment != null) {
        // attach added to handle viewpager fragments
        FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
        trans.replace(R.id.content_frame, fragment).attach(fragment)
            .addToBackStack(null);

        trans.commit();
        getFragmentManager().executePendingTransactions();
    } else {
        Log.d("Drawer Activity","Error in creating Fragment");
    }
}

1
我有同样的问题。这不是常见的。它在20次尝试中发生1次。 当onActivityCreated被创建时,视图可能为空或部分视图可能为空... 我添加而不是替换。 - apmartin1991
@apmartin1991,你能在这里提供你的代码片段吗?比如说在gist.github.com上发布,这样更容易理解根本原因。例如,在原始帖子中调用了.attach()函数,但是它不应该被调用,在您的问题上也没有必要调用executePendingTransactions()函数,但我们并不知道您的问题具体是什么。 - Konstantin Loginov
Konstantin Loginov - 这是我关于同样问题的提问 http://stackoverflow.com/questions/34742360/fragment-transaction-loads-a-blank-view - apmartin1991
@apmartin1991 我已经在那里回答了。我认为问题是由于使用executePendingTransactions并在现有片段之上添加片段造成的,这通常是不好的做法,因为两者都会保留在内存中并保持活动状态。 - Konstantin Loginov
5个回答

4

对于导航菜单片段事务,我使用以下方法,这样片段将被添加并放置在顶部。

String name = "myFragment";
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_frame, fragment, name)
.commit();

查找attach()函数。它遵循不同的片段生命周期。同时确保您的布局文件framelayout是可见的。


0

请按以下方式修改您的代码:

if(fragment != null) {
        // attach added to handle viewpager fragments
        FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
        trans.replace(R.id.content_frame, fragment);
        trans.addToBackStack(null);
        trans.commit();
    } else {
        Log.d("Drawer Activity","Error in creating Fragment");
    }

如果这个解决方案对你不起作用,那么请分享你的 XML 代码和片段代码。

1
这不就是抄袭@Veedka的答案吗? - Konstantin Loginov

0
我的解决方案是在片段替换时为所有片段打上唯一标签。确保在创建默认片段时也分配一个唯一标签。更有效的方法是在重新创建相同片段之前先识别该片段。
public void selectNavActivty(int position){
// TODO Changing between the different screens selection

    FragmentManager fragmentManager = getSupportFragmentManager();
    fragment = fragmentManager.findFragmentById(R.id.content_frame);
    String fragmentTag = null;
    switch (position) {
        case 0:
            fragmentTag = "case0Tag"; // please change to better tag name
            break;
        case 1: 
            fragmentTag = "case1Tag"; // please change to better tag name
            break;
        default:
            Log.d("Drawer Activity","Error in creating Fragment");
            return;
    }
    if (fragmentTag != null && !fragment.getTag().equals(fragmentTag))
    fragmentManager.beginTransaction().replace(R.id.content_fragment, fragment, tag).commit();
}

0
添加 Fragment 后,它将被添加到 Activity 状态中,并且其视图将被添加到定义的容器视图中。但是,如果 Fragment 尚未添加到 UI 中,则不会显示任何内容。它只是附加到 Fragment 管理器上。但是,如果视图已经添加到 UI 中的容器中并在此之后被分离,通过附加它将再次显示在其容器中。最后,如果您想暂时销毁 Fragment 视图并希望在未来显示和构建其视图而不会失去其在 Activity 中的状态,则可以使用 attach 和 detach。

https://dev59.com/5WQn5IYBdhLWcg3wn4RS#18979024


0
在我的情况下,旋转设备后显示了一个空白片段。我明白在 Activity.onCreate() 中,我总是调用创建一个空白的 Fragment,然后是需要的一个。所以我改变了它的行为:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    if (savedInstanceState == null) {
        openEmptyFragment()
        openAnotherFragment()
    }
}

我建议在添加新的片段之前检查savedInstanceState != null,正如为什么屏幕旋转时片段不会保留状态?中所写的那样。


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