我抓取了EU4You sample project中演示的The Busy Coder's Guide to Android Development 4.2(由Mark Murphy aka 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

主布局文件(大布局):

<?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"
/>

该示例应用程序的原始版本具有两个 Activity (准确地说是SherlockFragmentActivities)。
  • EU4You-加载适当的布局(默认或横向较大)。如果默认,则在SherlockListFragment中加载国家列表。如果为横向,则加载列表和详细信息 fragment 以显示所选国家/地区。
  • DetailsActivity-当不使用横向大布局时,通过DetailsFragment加载所选国家/地区。

  • 如果单击列表 fragment 中的国家,则EU4You(主要托管 Activity )将​​检查DetailsFragment的存在和可见性。如果存在,它将在该 fragment 内加载国家/地区网站。如果不是,它将触发DetailsActivity,然后再处理添加DetailsFragment(然后加载给定国家/地区的网站)。

    就像在平板电脑和手机上支持多种屏幕布局的典型应用程序一样,这可以正常工作。

    我的问题是我想删除DetailsActivity并坚持执行单个 Activity 。每当我不在大的横向布局中时(我在平板电脑上以纵向布局在手机上或以任何方向在手机上以纵向布局),我都想用细节 fragment 交换(替换)列表 fragment 。因此,我所做的是在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);
        }
    }
    

    我修改后的单一 Activity 版本:
    @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);
        }
    }
    

    这按预期工作。我单击列表上的一个网站(在平板电脑上以纵向模式,或在任何方向上在手机上以纵向),详细信息显示在详细信息 fragment 中,该 fragment 取代了网站列表 fragment 。但是,如果我单击设备上的主页按钮,同时显示国家(地区)详细信息,则会出现强制关闭错误,并显示以下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);
    

    我确实需要能够将replace事务添加到Backstack中,所以我不能删除此行(此示例应用程序是我的实际应用程序的基础,该应用程序具有更多的功能,但我使用它来简化问题)。

    有两个问题:
  • 为什么会这样?
  • 我该如何解决(也许是另一种方法)?

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

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

    我已经在GitHub上发布了一个示例项目。我是Eclipse和Android开发的新手,所以我可能未包含我需要的所有内容(未包含工作区,并且我不认为ActionBarSherlock项目已包含在内……它需要导入(可以在here中找到) )。

    最佳答案

    我无法对您的特定崩溃进行评论,因为我没有看到该错误,只能推测它与replace()绑定(bind)在一起,而不是使用attach()/detach()(只是一个猜测)而已。

    但是,getSupportFragmentManager().executePendingTransactions();对我来说是一种代码味道。我的猜测是您这样做是为了details.loadUrl(url);的好处。相反,请在DetailsFragment中添加一个数据成员,类似于urlToBeApplied,如果loadUrl()不存在,则让WebView将值存储在那里。然后,它可以在onCreateView()中应用URL。我不能说这是否对您的车祸有所帮助。

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

    更新

    基于示例应用程序,我能够更好地诊断问题。
    Content view not yet created上的ListFragment表示我们试图为尚未通过getListView()或已通过onCreateView()的 fragment 调用onDestroyView()。这通常表示时序问题。

    事实证明,在这种情况下,崩溃的工作无论如何都是多余的。 onSaveInstanceState()试图保持选中项的位置,因此我们可以稍后再进行检查(例如,在更改配置后)。但是,当我们在normal显示器上时,我们甚至不需要首先处于检查模式。选中的模式适用于activated状态,当列表和详细信息并排放置时,此模式才相关;而当列表和详细信息不相关时,则不相关。因此,解决方法是在不需要持久选择的情况下根本不打扰onSaveInstanceState()逻辑...我们可以通过在isPersistentSelection()上调用listener轻松获得此选择。

    但是,为了争辩,我们假装我们确实需要进行这项工作。在这种情况下,我们有两个选择。最简单的方法可能是重写onDestroyView()并缓存选中的项目位置,如果onSaveInstanceState()返回getListView(),则在null中使用该位置。

    关于android - 无法暂停 Activity ,尚未创建内容 View ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13424332/

    10-11 00:00