java 没有视图的片段在配置更改时崩溃
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4937075/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Fragment without a view crashes on configuration change
提问by alexanderblom
I have an UI where I need a Fragment
to be displayed (with a view) in landscape mode but not in portrait mode. In portrait mode it should still be available but will display its result using ListPopupWindow
instead.
我有一个 UI,我需要在其中Fragment
以横向模式而不是纵向模式显示(带有视图)。在纵向模式下,它应该仍然可用,但会使用它来显示其结果ListPopupWindow
。
I figured I could handle this by using the <fragment />
tag for the landscape layout while creating the fragment programmatically if it wasn't started (in the case when we are in portrait).
我想我可以通过使用<fragment />
横向布局的标签来处理这个问题,同时如果它没有启动(在我们纵向的情况下)以编程方式创建片段。
This works fine as long as you start out in landscape, if you start in portrait where the fragment is created programmatically your application will crash when you rotate the emulator when it tries to attach the fragment to your layout:
只要您以横向方式开始,这就可以正常工作,如果您以纵向方式开始以编程方式创建片段,当您尝试将片段附加到您的布局时旋转模拟器时,您的应用程序将崩溃:
java.lang.IllegalStateException: Fragment did not create a view. at android.app.Activity.onCreateView(Activity.java:4095)
java.lang.IllegalStateException:片段没有创建视图。在 android.app.Activity.onCreateView(Activity.java:4095)
The docs for Fragment.isInLayout()
seems to hint that it should be able to handle it this way:
的文档Fragment.isInLayout()
似乎暗示它应该能够以这种方式处理它:
Return true if the layout is included as part of an activity view hierarchy via the tag. This will always be true when fragments are created through the tag, except in the case where an old fragment is restored from a previous state and it does not appear in the layout of the current state.
如果布局通过标签作为活动视图层次结构的一部分包含在内,则返回 true。当通过标签创建片段时,这将始终是正确的,除非旧片段从先前状态恢复并且它没有出现在当前状态的布局中。
So the question is how to do this correctly or if there is something I'm missing?
所以问题是如何正确地做到这一点,或者我是否遗漏了什么?
UPDATE:
更新:
Seems like isInLayout()
isn't behaving as it should currently as well. It returns false if you have added a Fragment
to a container manually.
似乎isInLayout()
也没有像现在那样表现。如果您Fragment
手动将 a添加到容器,则返回 false 。
Also, if you add a Fragment
manually to a container and then rotate (the device) to a layout that does not contain that layout it will crash:
此外,如果您Fragment
手动向容器添加一个,然后将(设备)旋转到不包含该布局的布局,它将崩溃:
Caused by: java.lang.IllegalArgumentException: No view found for id 0x7f060011 for fragment SearchFragment{4042f868 #2 id=0x7f060011 SearchFragment} at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:722)
引起:java.lang.IllegalArgumentException:在 android.app.FragmentManagerImpl.moveToState(FragmentManager.java:722) 找不到片段 SearchFragment{4042f868 #2 id=0x7f060011 SearchFragment} id 0x7f060011 的视图
回答by Blake Meike
Have you come up with an answer to this? I was having a similar problem, and managed to come up with a solution. You can easily do what you are attempting as follows:
你有没有想出答案?我遇到了类似的问题,并设法提出了解决方案。您可以轻松地执行您正在尝试的操作,如下所示:
Create two different layouts one in the layout directory, one in the layout-land directory. The one in the layout-land directory will be used in landscape mode. As a placeholder, where you want your fragment to go, use s FrameLayout element, and id it, say with the id "my_fragment". The layout in the layout directory should not contains any element with that id.
创建两种不同的布局,一种在 layout 目录中,一种在 layout-land 目录中。layout-land 目录中的一个将用于横向模式。作为占位符,你想让你的片段去哪里,使用 s FrameLayout 元素,并标识它,用标识“my_fragment”说。布局目录中的布局不应包含任何具有该 ID 的元素。
In your onCreate method, use findViewById(R.id.my_fragment) to locate the fragment placeholder. If it exists, you are in landscape mode and should add your fragment (if it does not exist already): add(R.id.my_fragment, new MyFragment, "myFragment). If you get null, you are in portrait mode and should not create the fragment.
在您的 onCreate 方法中,使用 findViewById(R.id.my_fragment) 来定位片段占位符。如果存在,则您处于横向模式并应添加您的片段(如果它尚不存在): add(R.id.my_fragment, new MyFragment, "myFragment)。如果您为 null,则您处于纵向模式并且应该不创建片段。
Be very careful that you never replace a fragment created using a tag, with one that you create dynamically in your program. A fragment for which isInLayout returns true is a completely different beast, that one for which it returns false. Their lifecycles are entirely different. Replacing one with the other will lead to the dreaded IllegalStateException "Fragment did not create a view" problem.
请务必小心,切勿将使用标签创建的片段替换为在程序中动态创建的片段。isInLayout 返回 true 的片段是一种完全不同的野兽,它返回 false 的那个片段。它们的生命周期完全不同。将一个替换为另一个将导致可怕的 IllegalStateException “Fragment did not create a view”问题。
-blake
-布莱克
回答by Marco RS
Your problem can also be due to not having a lanscape layout for the fragment you are using. You might have one for the portrait and so your program runs fine but when you rotate your device, the OS probably looks for the view in the landscape folder and doesnt find the view so declares it as missing. Check that you have view both in the folder "layout" and "layout-land".
您的问题也可能是由于您使用的片段没有横向布局。您可能有一个用于纵向的,因此您的程序运行良好,但是当您旋转设备时,操作系统可能会在横向文件夹中查找视图,但没有找到该视图,因此将其声明为丢失。检查您是否在文件夹“layout”和“layout-land”中都有视图。