【发布时间】:2026-02-01 10:50:02
【问题描述】:
有一些类似的答案,但不是针对这种情况。
我的情况很简单。
我有一个具有两种不同布局的 Activity,一种是纵向的,另一种是横向的。
在Portrait中,我使用<FrameLayout>并将Fragment添加到其中动态。
在横向中,我使用<fragment>,所以Fragment是静态。 (其实这无关紧要)
它首先从纵向开始,然后我简单地添加了Fragment:
ListFrag listFrag = new ListFrag();
getSupportFragmentManager().beginTransaction()
.replace(R.id.FragmentContainer, listFrag).commit();
ListFrag extends ListFragment.
然后我做一个屏幕旋转。 我发现 listFrag 正在横向模式下重新创建。
(其中我注意到onCreate() 方法再次使用非空Bundle 调用)
我尝试像@NPike 在this post 中所说的那样使用setRetainInstance(false)。但是getRetainInstance() 默认已经是false。正如the docs 所说,它没有达到我的预期。谁能解释一下?
我正在处理的片段是ListFragment,它在onCreate() 中执行setListAdapter()。所以这里不能使用if (container == null) return null; method。 (或者我不知道如何申请)。
我从this post 那里得到了一些提示。我应该在我的ListFragment 中使用if (bundle != null) setListAdapter(null); else setListAdapter(new ...); 吗?但是,有没有更好的方法在片段被销毁/分离时确实删除/删除片段,而不是在创建时执行它? (如if (container == null) return null;方法)
编辑:
我发现的唯一巧妙方法是在onSaveInstanceState() 中执行getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.id.FragmentContainer)).commit();。但这会引发另一个问题。
当屏幕被部分遮挡时,如 WhatsApp 或 TXT 对话框弹出,片段也会消失。 (这是相对较小的,只是视觉问题)
当屏幕旋转时,Activity 被完全销毁并重新创建。所以我可以在
onCreate(Bundle)或onRestoreInstanceState(Bundle)中重新添加片段。但是在 (1) 的情况下,除了切换活动之外,当用户返回我的活动时,onCreate(Bundle)和onRestoreInstanceState(Bundle)都不会被调用。我无处可重新创建 Activity(并从 Bundle 中检索数据)。
对不起,我没有说清楚,我已经做出了决定,getSupportFragmentManager()...replace(...).commit(); 行仅在纵向模式下运行。
示例代码
我已经提取了简单的代码,以便更好地说明情况:)
MainActivity.java
package com.example.fragremovetrial;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.FragmentContainer) != null) {
System.out.println("-- Portrait --"); // Portrait
ListFrag listFrag = new ListFrag();
getSupportFragmentManager().beginTransaction()
.replace(R.id.FragmentContainer, listFrag).commit();
} else {
System.out.println("-- Landscape --"); // Landscape
}
}
@Override
protected void onResume() {
super.onResume();
if (findViewById(R.id.FragmentContainer) != null) {
System.out.println("getRetainInstance = " +
getSupportFragmentManager().findFragmentById(R.id.FragmentContainer).getRetainInstance());
}
}
}
layout/activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/FragmentContainer"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
layout-land/activity_main.xml (没关系)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
ListFrag.java
package com.example.fragremovetrial;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.widget.ArrayAdapter;
public class ListFrag extends ListFragment {
private String[] MenuItems = { "Content A", "Contnet B" };
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("ListFrag.onCreate(): " + (savedInstanceState == null ? null : savedInstanceState));
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, MenuItems));
}
}
注意我得到了以下内容
调试消息
-- 肖像--
ListFrag.onCreate(): null
getRetainInstance = false
(旋转端口 -> 陆地)
ListFrag.onCreate(): 捆绑[{android:view_state=android.util.SparseArray@4052dd28}]
-- 风景 --
以前聚焦的视图在保存期间报告 id 16908298,但在恢复期间找不到。
(旋转土地 -> 端口)
ListFrag.onCreate(): 捆绑[{android:view_state=android.util.SparseArray@405166c8}]
-- 肖像 --
ListFrag.onCreate(): null
getRetainInstance = false
(旋转端口 -> 陆地)
ListFrag.onCreate(): Bundle[{android:view_state=android.util.SparseArray@4050fb40}]
-- 风景 --
以前聚焦的视图在保存期间报告 id 16908298,但在恢复期间找不到。
(旋转土地 -> 端口)
ListFrag.onCreate(): 捆绑[{android:view_state=android.util.SparseArray@40528c60}]
-- 肖像 --
ListFrag.onCreate(): null
getRetainInstance = false
创建的片段数量不会随着屏幕不断旋转而无限增加,我无法解释。 (请帮忙)
【问题讨论】:
-
在进一步阅读docs 之后,我想我明白为什么
setRetainInstance(false)在我的情况下不起作用。 (1)当setRetainInstance(true)时,正如文档所说,它调用onDetach()然后onAttach(),并跳过onDestroy()和onCreate()。 (2) 因此,这意味着当setRetainInstance(false)时,片段将是onDestroy(),然后是onCreate(Bundle)。这意味着setRetainInstance()不是处理“保留/删除”片段的东西。它只控制“保留/重新创建”它。 -
对*.com/questions/15536679/…进行更结构化的检查
标签: android android-fragments android-listfragment android-fragmentactivity android-framelayout