【问题标题】:Fragment unable to restore correct View on rotate片段无法在旋转时恢复正确的视图
【发布时间】:2014-10-16 21:31:45
【问题描述】:

我正在使用具有两个主要视图的片段,这些视图具有 setVisibility() 根据用于在线搜索数据的 AsyncTask 的结果显示或隐藏。

例如,这里是Views之间切换的方法:

private void switchView()
{
    Log.d(LOG_TAG, "switchView(): show = " + show);
    mListView.setVisibility(show ? View.VISIBLE : View.GONE);
    searchView.setVisibility(show ? View.GONE : View.VISIBLE);
    mCompanyArrayAdapter.notifyDataSetChanged();
}

我正在采用这种方法,以便在 AsyncTask 完成后,它可以将数据解析为包装类并创建这些对象的 ArrayList 以在 ListView 适配器中使用。 (如果有其他方法可以将自定义类传递给另一个片段,我愿意使用它。)

一旦结果 == true 从异步它隐藏 searchView 并显示 mListView。但是在旋转时,屏幕会返回到 searchView,而不是继续显示 mListView 结果。

我对 Log 输出感到困惑,该输出显示了我认为从同一片段 (DiscoverFragment) 对 onCreateView 的两次调用,见此处:

10-17 10:29:21.872    6603-6603/nz.co.exium.panther D/DiscoverFragment﹕ onCreateView: savedinstancestate is null = false
10-17 10:29:21.877    6603-6603/nz.co.exium.panther D/AbsListView﹕ Get MotionRecognitionManager
10-17 10:29:21.882    6603-6603/nz.co.exium.panther D/DiscoverFragment﹕ onCreateView: savedinstancestate is null = true

因此,第一个显示已找到 savedInstanceState != null 并适当地设置布尔值,但随后调用另一个 onCreateView(),其中 savedInstanceState 为 null 并将其设置回 false。为什么旋转后出现双 onCreateView()?

感谢您的帮助。

根据要求,替换 MainActivity 中的片段的代码(对 content_frame 和 position == DrawerLayout 位置项使用 FrameLayout)。:

getFragmentManager().beginTransaction()
                    .replace(R.id.content_frame, Fragment.instantiate(
                            getApplicationContext(), mClasses[position]))
                    .commit();

来自我的 MainActivity.onCreate():

if (savedInstanceState == null) {
        selectItem(0);
    } else if (placeID == null || placeID.isEmpty()) {
        selectItem(savedInstanceState.getInt(SELECTED_KEY));
    }   else    {
        selectItem(2);
    }

我已经对之前的 savedInstanceState 进行了检查,如果为 null 则设置默认 Fragment。如果变量 placeID(来自 BroadcastReceiver)为空/空,则恢复之前的状态。否则,转到将显示通知数据的片段。

【问题讨论】:

  • 您能否在将片段添加到活动的位置添加代码(我假设您是以编程方式添加它,而不是通过 XML 中的 <fragment>)?
  • 是的,使用 DrawerLayout,方法 selectItem(int position) 使用我在问题中添加的代码切换 content_frame 中的片段。
  • 那么在您的活动的onCreate() 中会发生什么以显示片段?
  • 关于savedInstanceState,如果它不为null,则检索最后一个fragment的保存位置,并使用selectItem(int position)方法显示最后一个fragment。

标签: java android listview android-fragments android-asynctask


【解决方案1】:

片段会在旋转时自动重新创建,作为恢复状态的一部分。因此,您应该只在savedInstanceState == null 时调用selectItem() - 否则您将获得恢复的片段(具有恢复状态),然后立即将其替换为全新的实例(没有恢复状态)。

【讨论】:

  • 是的,看起来我在那里有不必要的代码来尝试恢复旋转状态。删除第二个条件允许该片段检索其正确的已保存状态。感谢您的帮助!
【解决方案2】:

所以,这里发生的事情是这样的:

  • 您的活动已创建,并向其中添加了一个片段
  • 你旋转你的设备
  • 您的活动被重新创建(连同之前添加的片段),并且在 onCreate 中,您添加了一个新片段,这意味着您在活动中添加了两个片段

处理此问题的最简单方法是检查您的活动:

if (savedInstanceState == null){    // add fragment }

另一种方法是通过在 AndroidManifest.xml 中指定配置更改来防止活动重新生成

【讨论】:

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