【问题标题】:Replacing fragments and orientation change替换片段和方向更改
【发布时间】:2011-07-28 08:44:43
【问题描述】:

我正在开发一个面向 2.x 和 3.0 设备的 Android 应用程序,因此我使用的是兼容 API。我正在 Android 2.0 上进行测试。

我正在尝试将显示的片段替换为另一个片段(带有搜索结果的搜索表单),当显示第二个(结果)片段时,我在方向更改时遇到崩溃。

基本上,我有一个活动,其中包括在布局 xml 中定义的片段

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

默认显示第一个片段 (SearchFormFragment)。当用户点击“搜索”按钮时,我将 SearchFormFragment 替换为 SearchResultsFragment,它运行 AsyncTask(这就是我想要保留它的原因)

    // 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();

但是,当显示 SearchFormFragment 并更改方向时,我的应用程序崩溃了

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 和状态变化的文档真的很缺乏。

【问题讨论】:

    标签: android backwards-compatibility screen-orientation android-2.2-froyo


    【解决方案1】:

    不要在 XML 中创建 SearchFormFragment。取而代之的是一个空的FrameLayout,您将其填充到Activity.onCreate() 中,而不将其添加到后台堆栈中。这样Activity 将保留当前的Fragment,而不是尝试添加XML 中指定的那个。

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

    【讨论】:

      【解决方案2】:

      在为此苦苦挣扎了几个小时后,我终于明白了。 问题根本不在于设置或我们调用 Fragment 类的方式。它与屏幕上显示的错误消息有关。如果您在 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));
          }
      

      【讨论】:

        【解决方案3】:

        出于参考原因:我们能够通过将android:id 添加到我们用 XML 创建的片段中来解决非常相似的问题。

        支持无崩溃旋转这个非常重要的前提只有mentioned as a side-note in the documentation

        注意:每个片段都需要一个唯一的标识符,系统可以 如果活动重新启动(以及哪个 您可以使用捕获片段来执行事务,例如 删除它)。

        【讨论】:

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