我的情况很简单.
我有一个具有两种不同布局的活动,一个在Portrait中,另一个在Landscape中.
在Portrait中,我使用< FrameLayout>并动态地将Fragment添加到其中.
在Landscape中,我使用< fragment>所以片段是静态的. (事实上这没关系)
它首先在Portrait中开始,然后我简单地添加了片段:
ListFrag listFrag = new ListFrag(); getSupportFragmentManager().beginTransaction() .replace(R.id.FragmentContainer,listFrag).commit();
其中ListFrag扩展了ListFragment.
然后我做一个屏幕旋转.我发现listFrag正在横向模式下重新创建.
(其中我注意到使用非null Bundle再次调用onCreate()方法)
我尝试使用setRetainInstance(false),就像@NPike在this post中说的那样.但是默认情况下getRetainInstance()已经是假的.它没有按照the docs所说的那样做.有人可以解释一下吗?
我正在处理的片段是ListFragment,它在onCreate()中执行setListAdapter().所以if (container == null) return null;
method不能在这里使用. (或者我不知道如何申请).
我从this post得到了一些提示.我应该使用if(bundle!= null)setListAdapter(null); else setListAdapter(new …);在我的ListFragment中?但是,当它被销毁/分离时,是否有更好的方法来删除/删除片段,而不是在创建时间内执行它? (所以if(container == null)返回null;方法)
编辑:
我找到的唯一简洁方法是执行getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.id.FragmentContainer)).commit();在onSaveInstanceState()中.但它会引发另一个问题.
>当屏幕被部分遮挡时,如WhatsApp或TXT对话框弹出,片段也会消失. (这是相对较小的,只是视觉问题)
>当屏幕旋转时,活动将被完全销毁并重新创建.所以我可以在onCreate(Bundle)或onRestoreInstanceState(Bundle)中重新添加片段.但是在(1)的情况下,以及切换活动时,当用户返回我的Activity时,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()); } } }
布局/ 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)); } }
请注意我得到以下内容
调试消息
— Portrait —
ListFrag.onCreate(): null
getRetainInstance = false(rotate Port -> Land)
ListFrag.onCreate(): Bundle[{android:view_state=android.util.SparseArray@4052dd28}]
— Landscape —
PrevIoUsly focused view reported id 16908298 during save,but can’t be found during restore.(rotate Land -> Port)
ListFrag.onCreate(): Bundle[{android:view_state=android.util.SparseArray@405166c8}]
— Portrait —
ListFrag.onCreate(): null
getRetainInstance = false(rotate Port -> Land)
ListFrag.onCreate(): Bundle[{android:view_state=android.util.SparseArray@4050fb40}]
— Landscape —
PrevIoUsly focused view reported id 16908298 during save,but can’t be found during restore.(rotate Land -> Port)
ListFrag.onCreate(): Bundle[{android:view_state=android.util.SparseArray@40528c60}]
— Portrait —
ListFrag.onCreate(): null
getRetainInstance = false
解决方法
The only neat way i found is doing
getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.id.FragmentContainer)).commit();
inonSaveInstanceState()
. But it will raise another problems…
……有一些改进.
在onSaveInstanceState()中:
@Override protected void onSaveInstanceState(Bundle outState) { if (isPortrait2Landscape()) { remove_fragments(); } super.onSaveInstanceState(outState); } private boolean isPortrait2Landscape() { return isDevicePortrait() && (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE); }
而isDevicePortrait()就像:
private boolean isDevicePortrait() { return (findViewById(R.id.A_View_Only_In_Portrait) != null); }
*请注意,我们不能使用getResources().getConfiguration().orientation来确定设备当前是字面上的肖像.这是因为在屏幕旋转后,Resources对象会更改 – 即使在调用onSaveInstanceState()之前!
如果我们不想使用findViewById()来测试方向(由于任何原因,并且它不是那么整洁),请保留一个全局变量private int current_orientation;并通过current_orientation = getResources()初始化它.getConfiguration().orientation;在onCreate()中.这似乎更整洁.但是我们应该注意不要在Activity生命周期中的任何地方改变它.
*确保我们在super.onSaveInstanceState()之前删除了remove_fragments().
(因为在我的情况下,我从布局和活动中删除碎片.如果它在super.onSaveInstanceState()之后,布局将已经保存到Bundle中.然后碎片也将在之后重新创建.活动重新创建.###)
###我已经证明了这一现象.但What to determine a Fragment restore upon Activity re-create?的原因仅仅是我的猜测.如果您对此有任何想法,请回答my another question.