无法暂停活动,内容视图尚未创建



我获得了在the Busy Coder’s Guide to Android Development 4.2中演示的EU4You示例项目(由Mark Murphy(又名commonsware)在StackOverflow上提供)。这个示例项目可能更容易理解,但我将尝试在问题中发布代码的相关部分。您还需要导入ActionBarSherlock项目。您还需要将Java编译器设置为1.6(以允许@Override注释)。

注意:我已将最小sdk更改为8(2.3,Froyo),将目标sdk改为16(4.1,Ice Cream Sandwich)

注意:我已将countries帧布局id更改为left_pane,将details帧布局id改为right_pane

主布局文件(大面积布局):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="@+id/left_pane"
android:layout_weight="30"
android:layout_width="0px"
android:layout_height="fill_parent"
/>
<FrameLayout
android:id="@+id/right_pane"
android:layout_weight="70"
android:layout_width="0px"
android:layout_height="fill_parent"
/>
</LinearLayout>

主布局文件:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/left_pane"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>

示例应用程序的原始版本有两个活动(确切地说是SherlockFragmentActivities)。

  1. EU4You-加载适当的布局(默认或横向大)。如果默认,则在SherlockListFragment中加载国家列表。如果横向较大,则加载列表和详细信息片段以显示所选国家/地区
  2. DetailsActivity-当而非使用横向大布局时,通过DetailsFragment加载所选国家/地区

如果您单击列表片段中的某个国家,EU4You(主要托管活动)将检查DetailsFragment的存在和可见性。如果它存在,它会加载该片段中的国家网站。如果没有,它会启动DetailsActivity,然后处理添加DetailsFragment(然后加载给定国家的网站)。

这很好,就像一个典型的应用程序支持平板电脑和手机上的多屏幕布局一样。

我的问题是,我想删除DetailsActivity并坚持使用单个活动。每当我不在大的横向布局中时(换句话说,我要么在平板电脑上处于纵向布局,要么在手机上处于任何方向),我都想用细节片段替换列表片段。因此,我所做的是在EU4You SherlockFragmentActivity中更改以下内容:

原始(对注释中提到的框架布局名称进行了轻微的命名修改…国家/地区为left _pane,详细信息为right _pane):

@Override
public void onCountrySelected(Country c) {
String url=getString(c.url);
if (details != null && details.isVisible()) {
details.loadUrl(url);
}
else {
Intent i=new Intent(this, DetailsActivity.class);
i.putExtra(DetailsActivity.EXTRA_URL, url);
startActivity(i);
}
}

我修改的单一活动版本

@Override
public void onCountrySelected(Country c) {
String url=getString(c.url);
if (details != null && details.isVisible()) {
details.loadUrl(url);
} 
else {
details = new DetailsFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.left_pane, details);
ft.addToBackStack(null);
ft.commit();
getSupportFragmentManager().executePendingTransactions();
details.loadUrl(url);
}
}

这是意料之中的事。我点击列表上的一个网站(在平板电脑上以人像模式,或在任何方向的手机上),详细信息显示在详细信息片段中,它取代了网站列表片段。然而,如果我在显示国家/地区详细信息的同时点击设备上的主页按钮,我会得到一个强制关闭错误,包括以下logcat详细信息(只有默认布局只有一个left_pane框架布局……当有left_paine和right_pane时,我在平板电脑的横向方向上没有这个问题):

11-16 15:04:33.525: E/AndroidRuntime(688): FATAL EXCEPTION: main
11-16 15:04:33.525: E/AndroidRuntime(688): java.lang.RuntimeException: Unable to pause activity {com.commonsware.android.eu4you/com.commonsware.android.eu4you.EU4You}: java.lang.IllegalStateException: Content view not yet created
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3348)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3305)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3288)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.app.ActivityThread.access$2500(ActivityThread.java:125)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2040)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.os.Handler.dispatchMessage(Handler.java:99)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.os.Looper.loop(Looper.java:123)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.app.ActivityThread.main(ActivityThread.java:4627)
11-16 15:04:33.525: E/AndroidRuntime(688):  at java.lang.reflect.Method.invokeNative(Native Method)
11-16 15:04:33.525: E/AndroidRuntime(688):  at java.lang.reflect.Method.invoke(Method.java:521)
11-16 15:04:33.525: E/AndroidRuntime(688):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
11-16 15:04:33.525: E/AndroidRuntime(688):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
11-16 15:04:33.525: E/AndroidRuntime(688):  at dalvik.system.NativeStart.main(Native Method)
11-16 15:04:33.525: E/AndroidRuntime(688): Caused by: java.lang.IllegalStateException: Content view not yet created
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.support.v4.app.ListFragment.getListView(ListFragment.java:222)
11-16 15:04:33.525: E/AndroidRuntime(688):  at com.commonsware.android.eu4you.CountriesFragment.onSaveInstanceState(CountriesFragment.java:64)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1574)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1644)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:499)
11-16 15:04:33.525: E/AndroidRuntime(688):  at com.actionbarsherlock.app.SherlockFragmentActivity.onSaveInstanceState(SherlockFragmentActivity.java:127)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.app.Activity.performSaveInstanceState(Activity.java:1036)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1180)
11-16 15:04:33.525: E/AndroidRuntime(688):  at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3330)
11-16 15:04:33.525: E/AndroidRuntime(688):  ... 12 more

如果我从上面的代码中删除以下行,我可以阻止这个错误的发生:

ft.addToBackStack(null);

我确实需要能够将替换事务添加到后台,所以我不能删除这一行(这个示例应用程序是我的真实应用程序的基础,它有更多的东西,但我用它来简化我的问题)。

所以有两个问题:

  1. 为什么会发生这种情况
  2. 我该如何修复它(也许是另一种方法)

需要注意的一点是,在我的实际应用程序中,此逻辑必须全部位于操作栏中的选项卡中(ActionBarSherlock,因为我必须支持版本2.3(Froyo))。


更新(2012-Nov-22 13:27 EST)

我在GitHub上发布了一个示例项目。我是Eclipse和Android开发的新手,所以我可能没有包括我需要的一切(工作区没有包括在内,我认为ActionBarSherlock项目也没有包括在内……它需要导入(可以在这里找到))。

我无法对您的特定崩溃发表评论,因为我没有看到那个错误,只是猜测它与replace()有关,而不是使用attach()/detach()(只是猜测)。

然而,getSupportFragmentManager().executePendingTransactions();对我来说是一种代码气味。我猜你这样做是为了details.loadUrl(url);的利益。相反,请在DetailsFragment中添加一个数据成员,类似于urlToBeApplied,如果WebView还不存在,请让loadUrl()将值存储在那里。然后,它可以在onCreateView()中应用URL。我不能说这是否有助于你的崩溃。

您可能希望考虑发布一个完整的示例项目来演示该问题,因为您希望人们能够识别错误消息。


更新

基于示例应用程序,我能够更好地诊断问题。

Content view not yet created,在ListFragment上,意味着我们试图为尚未通过onCreateView()通过onDestroyView()的片段调用getListView()。这通常表示时间问题。

事实证明,在这种情况下,崩溃的工作无论如何都是多余的。onSaveInstanceState()正试图保留已检查项目的位置,因此我们可以稍后重新检查(例如,在配置更改后)。然而,当我们在normal显示器上时,我们甚至不需要首先处于检查模式。选中的模式适用于activated状态,当列表和详细信息并列时,这是相关的,但当它们不并列时,它是不相关的。因此,如果我们不需要持久选择,解决方法就是简单地不使用onSaveInstanceState()逻辑。。。我们可以通过在CCD_ 25上调用CCD_。

不过,为了便于争论,让我们假设我们确实需要做这项工作。在这种情况下,我们有几个选择。最简单的可能是覆盖onDestroyView()并缓存检查项的位置,如果getListView()返回null,则使用onSaveInstanceState()中的位置。

最新更新