19

我正在开发一款面向2.x和3.0设备的Android应用程序,因此我使用兼容性API。我正在测试Android 2.0。替换碎片和方向更改

我试图用另一个(与搜索结果搜索窗体)替换显示的片段,并且当第二个(结果)片段显示时遇到方向更改崩溃。

基本上,我有一个活动,其包括如

<fragment class="org.prevoz.android.search.SearchFormFragment" 
       android:id = "@+id/search_form_fragment" 
       android:layout_width = "fill_parent" 
       android:layout_height = "fill_parent" /> 

第一个片段(SearchFormFragment)被显示为缺省布局中定义的XML片段。当用户点击“搜索”按钮,我更换SearchResultsFragment,它运行的的AsyncTask的SearchFormFragment(这就是为什么我要保留它)时会显示SearchFormFragment和方向改变与

// Show the search results fragment 
SearchResultsFragment newSearch = new SearchResultsFragment(from, to, when); 
newSearch.setRetainInstance(true); 

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); 
transaction.replace(R.id.search_form_fragment, newSearch);  
transaction.addToBackStack(null); 
transaction.commit(); 

然而,我与

ERROR/AndroidRuntime(334): FATAL EXCEPTION: main 
ERROR/AndroidRuntime(334): java.lang.RuntimeException: Unable to start activity ComponentInfo{org.prevoz.android/org.prevoz.android.search.MainActivity}: android.view.InflateException: Binary XML file line #13: Error inflating class fragment 
ERROR/AndroidRuntime(334):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663) 
ERROR/AndroidRuntime(334):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) 
ERROR/AndroidRuntime(334):  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3815) 
ERROR/AndroidRuntime(334):  at android.app.ActivityThread.access$2400(ActivityThread.java:125) 
ERROR/AndroidRuntime(334):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2037) 
ERROR/AndroidRuntime(334):  at android.os.Handler.dispatchMessage(Handler.java:99) 
ERROR/AndroidRuntime(334):  at android.os.Looper.loop(Looper.java:123) 
ERROR/AndroidRuntime(334):  at android.app.ActivityThread.main(ActivityThread.java:4627) 
ERROR/AndroidRuntime(334):  at java.lang.reflect.Method.invokeNative(Native Method) 
ERROR/AndroidRuntime(334):  at java.lang.reflect.Method.invoke(Method.java:521) 
ERROR/AndroidRuntime(334):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
ERROR/AndroidRuntime(334):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
ERROR/AndroidRuntime(334):  at dalvik.system.NativeStart.main(Native Method) 
ERROR/AndroidRuntime(334): Caused by: android.view.InflateException: Binary XML file line #13: Error inflating class fragment 
ERROR/AndroidRuntime(334):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:582) 
ERROR/AndroidRuntime(334):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:618) 
ERROR/AndroidRuntime(334):  at android.view.LayoutInflater.inflate(LayoutInflater.java:407) 
ERROR/AndroidRuntime(334):  at android.view.LayoutInflater.inflate(LayoutInflater.java:320) 
ERROR/AndroidRuntime(334):  at android.view.LayoutInflater.inflate(LayoutInflater.java:276) 
ERROR/AndroidRuntime(334):  at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198) 
ERROR/AndroidRuntime(334):  at android.app.Activity.setContentView(Activity.java:1647) 
ERROR/AndroidRuntime(334):  at org.prevoz.android.search.MainActivity.onCreate(MainActivity.java:40) 
ERROR/AndroidRuntime(334):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 
ERROR/AndroidRuntime(334):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627) 
ERROR/AndroidRuntime(334):  ... 12 more 
ERROR/AndroidRuntime(334): Caused by: java.lang.IllegalStateException: Fragment org.prevoz.android.search.SearchFormFragment did not create a view. 
ERROR/AndroidRuntime(334):  at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:281) 
ERROR/AndroidRuntime(334):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:558) 
ERROR/AndroidRuntime(334):  ... 21 more 
WARN/ActivityManager(59): Force finishing activity org.prevoz.android/.search.MainActivity 

从SearchFormFragment相关onCreateView代码的应用程序崩溃不会被调用,我返回一个有效的视图:

@Override 
public View onCreateView(LayoutInflater inflater, 
         ViewGroup container, 
         Bundle savedInstanceState) 
{  
    View newView = inflater.inflate(R.layout.search_form_frag, container, false); 
    return newView; 
} 

仅在显示SearchResultsFragment时发生崩溃,如果显示默认的SearchFormFragment,则更改将正常工作。

那么如何通过方向更改保留第二个片段状态?关于API和状态变化的文档是非常缺乏的。

回答

28

不要在XML中创建SearchFormFragment。而是有一个空的FrameLayout,您将其填入Activity.onCreate()而不将其添加到后退堆栈。这样Activity将保持当前的Fragment,而不是试图添加XML中指定的那个。

此外,使用AsyncLoader可能是一个更好的方法,请参阅http://code.google.com/p/android/issues/detail?id=14944

+0

我用装载机来解决我的问题,它工作。谢谢。 – Mavrik 2011-04-14 18:08:43

+0

你让我的一天:) – Oli 2011-12-27 14:18:05

4

与此挣扎了几个小时后,我终于得到它。 问题不在于设置或我们称之为片段类的方式。它与屏幕上显示的错误信息有关。如果您在Ftagment类的onCreateView()中检查了容器为空,则会得到“无法膨胀碎片”消息,而不是容器为空消息。所以,不要检查你的onCreateView()中的空容器。因此,请确保您的onCreateView()看起来是这样的:

@Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     return(inflater.inflate(R.layout.title_layout, container, false)); 
    } 

,而不是像这样:

@Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     if(container == null){ 
      return null;         
     } 
     return(inflater.inflate(R.layout.title_layout, container, false)); 
    } 
+0

你不应该在'onCreateView()'提供的容器中使用'Inflator.inflate',在完成'onCreateView()'后自动添加父项。相反,你应该充气通过'null'作为容器参数。 – Graeme 2012-07-13 09:47:28

+0

这是违反直觉的。那么什么是'容器'的意义呢? – Cheezmeister 2012-08-14 15:51:29

+0

@Graeme“false”的最后一个参数意味着你实际上并没有将充气的视图附加到容器上,并且容器被传递,因此右侧的'LayoutParam'被用于充气视图。 – 2013-02-14 17:37:12

4

供参考的原因:我们可以通过添加android:id我们的片段来解决一个非常类似的问题用XML创建。

支持无碰撞旋转这个非常重要的前提条件是只有mentioned as a side-note in the documentation

注:每个片段都需要一个唯一的标识符,该系统能 使用还原如果活动重启片段(和其你可以使用 来捕获片段来执行交易,例如 将其删除)。

+0

这是唯一正确的答案。 – mkuech 2015-07-30 15:50:30