我抓住EU4You sample project中展示的The Busy Coder's Guide to Android Development 4.2(由Mark Murphy提供,又名commonsware来自StackOverflow)。跟随此示例项目可能更容易,但我将尝试在问题中发布相关的代码部分。您还需要导入ActionBarSherlock项目。您还需要将Java编译器设置为1.6(以允许@Override注释)。
注意:我已将min-sdk更改为8(2.3,Froyo),将target-sdk更改为16(4.1,Ice Cream Sandwich)。
注意:我已将countries
framelayout ID更改为left_pane
,将details
framelayout ID更改为right_pane
。
主要布局文件(layout-large-land):
<?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)。
如果单击列表片段中的国家/地区,EU4You(主要托管活动)将检查DetailsFragment的存在和可见性。如果存在,则会在该片段内加载国家/地区网站。如果没有,它将触发DetailsActivity,然后处理添加DetailsFragment(然后加载给定国家/地区的网站)。
这很好用,就像在平板电脑和手机上支持多种屏幕布局的典型应用程序一样。
我的问题是我要删除DetailsActivity并坚持单个活动。每当我不在大型横向布局中时,我想用详细信息片段替换(替换)列表片段(换句话说,我要么是在平板电脑上的纵向布局,要么是在任何方向的手机上)。所以我所做的,改变了EU4You SherlockFragmentActivity中的以下内容:
原始(对进一步注释中提到的framelayout名称进行轻微命名修改...国家/地区为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 framelayout ...我不知道当存在left_pane和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);
我确实需要能够将替换事务添加到backstack,所以我无法删除此行(此示例应用程序是我的实际应用程序的基础,有更多的东西,但我用它来简化我的问题)。
所以有两个问题:
需要注意的一点是,在我的实际应用程序中,此逻辑必须全部属于操作栏中的选项卡(ActionBarSherlock,因为我必须支持返回2.3版(Froyo))。
更新(2012年11月22日13:27美国东部时间)
我在GitHub上发布了一个示例项目。我是Eclipse和Android开发的新手,因此我可能没有包含我需要的所有内容(工作区未包含在内,我认为ActionBarSherlock项目不包括在内......它需要导入(可以找到{{ 3}}))。
答案 0 :(得分:5)
我无法评论您的具体崩溃,因为我没有看到该错误,只是猜测它与replace()
相关而非使用attach()
/ detach()
(只是一个猜测)。
然而,getSupportFragmentManager().executePendingTransactions();
给我的是代码气味。我的猜测是你为了details.loadUrl(url);
的利益而这样做。相反,请在DetailsFragment
中添加数据成员,例如urlToBeApplied
,如果loadUrl()
尚不存在,请WebView
存储值。然后,它可以在onCreateView()
中应用该网址。这是否有助于你的崩溃,我不能说。
您可能希望考虑发布一个演示该问题的完整示例项目,因为您指望有人识别错误消息。
<强>更新强>
基于示例应用程序,我能够更好地诊断问题。
Content view not yet created
上的{p> ListFragment
表示我们正在尝试拨打getListView()
以查找尚未通过onCreateView()
或的片段< / em>经历了onDestroyView()
。这通常表明存在时间问题。
在这种情况下,事实证明,无论如何,崩溃的工作是多余的。 onSaveInstanceState()
正试图保留已检查的项目位置,因此我们可以稍后重新检查它(例如,在配置更改后)。但是,当我们在normal
显示时,我们甚至不需要首先处于检查模式。已检查模式适用于activated
状态,当列表和详细信息并排时,这是相关的,但如果不是,则无关紧要。因此,如果我们不需要持久选择,那么解决方法就是不要理会onSaveInstanceState()
逻辑......我们可以通过调用isPersistentSelection()
上的listener
来轻松获取。
但是,为了争论,让我们假装我们确实需要做这项工作。在这种情况下,我们有几个选择。最简单的可能是覆盖onDestroyView()
并缓存选中的项目位置,如果onSaveInstanceState()
返回getListView()
,则使用null
中的位置。