Bog*_*rac 5 android android-fragments android-fragmentactivity android-nested-fragment
信息:我有一个2窗格布局(2个孩子Fragments)ParentFragment,当然,它在一个内部FragmentActivity.我setRetainInstance(true)的ParentFragment.在方向更改时,左子片段不会被销毁(onCreate()不会被调用),这是正常的(因为父节点保留其实例).
问题:在方向改变时,正确的片段被破坏(onCreate()被调用).为什么地狱是正确的片段被破坏而左边的片段不是?
编辑:如果我删除setRetainInstance(true),那么左边的片段onCreate()被调用两次(lol wtf),右边的片段onCreate()被调用一次.所以这也不好......
ParentFragment的代码如下:
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_schedule, container, false);
setHasOptionsMenu(true);
if (getChildFragmentManager().findFragmentById(R.id.fragment_schedule_framelayout_left) == null ||
!getChildFragmentManager().findFragmentById(R.id.fragment_schedule_framelayout_left).isInLayout())
{
if (mPresentationsListFragment == null)
mPresentationsListFragment = PresentationsListFragment.newInstance(PresentationsListFragment.TYPE_SCHEDULE, mScheduleDate);
getChildFragmentManager().beginTransaction()
.replace(R.id.fragment_schedule_framelayout_left, mPresentationsListFragment)
.commit();
}
mPresentationsListFragment.setOnPresentationClickListener(this);
return view;
}
@Override
public void onPresentationClick(int id)
{
if (Application.isDeviceTablet(getActivity()))
{
if (getChildFragmentManager().findFragmentById(R.id.fragment_schedule_framelayout_right) == null)
{
if (mPresentationDetailFragment == null)
mPresentationDetailFragment = PresentationDetailFragment.newInstance(id);
else
mPresentationDetailFragment.loadPresentation(id);
getChildFragmentManager().beginTransaction()
.replace(R.id.fragment_schedule_framelayout_right, mPresentationDetailFragment)
.commit();
}
else
mPresentationDetailFragment.loadPresentation(id);
}
else
{
Intent presentationDetailIntent = new Intent(getActivity(), PresentationDetailActivity.class);
presentationDetailIntent.putExtra(PresentationDetailActivity.KEY_PRESENTATION_ID, id);
startActivity(presentationDetailIntent);
}
}
Run Code Online (Sandbox Code Playgroud)
LE解决方案:非常
感谢antonyt,答案如下.执行pe所需的唯一更改位于父级的onCreateView()内Fragment.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_schedule, container, false);
setHasOptionsMenu(true);
if (getChildFragmentManager().findFragmentById(R.id.fragment_presentations_framelayout_left) == null)
{
mPresentationsListFragment = PresentationsListFragment.newInstance();
mPresentationsListFragment.setOnPresentationClickListener(this);
getChildFragmentManager().beginTransaction()
.add(R.id.fragment_presentations_framelayout_left, mPresentationsListFragment)
.commit();
}
return view;
}
Run Code Online (Sandbox Code Playgroud)
根据我的理解,如果您setRetainInstance(true)使用上面的代码在父片段上,那么在更改方向时,应该重新创建左侧片段,但右侧片段不应该重新创建.这与你上面写的内容相反,但我会解释为什么会出现这种情况.如果你有setRetainInstance(false)父片段,你确实应该看到左片段被创建两次而右片段被创建一次.
情况1: setRetainInstance(true)
您的父片段在轮换时不会被销毁.但是,它仍然会每次重新创建其视图(onDestroyView并将按此onCreateView顺序调用).在onCreateView你的代码添加在一定条件下你的左边片段.getChildFragmentManager().findFragmentById(R.id.fragment_schedule_framelayout_left)应该是非null,因为先前已将一个片段添加到该容器中.getChildFragmentManager().findFragmentById(R.id.fragment_schedule_framelayout_left).isInLayout() 应该是假的,因为只有通过XML添加的片段才会使它返回true.总体情况是正确的,因此将创建左侧片段的新实例,它将替换旧的实例.您的正确片段仅在单击事件期间实例化,因此不会发生特殊行为.
摘要:父片段仍然存在,新的左片段被创建,右片段仍然存在.
案例2: setRetainInstance(false)
您的父片段被破坏,左右片段也被破坏.所有三个片段都由Android自动重建.然后,您的父片段将有机会创建其视图,并将根据上述说明创建左片段的新实例.刚刚创建的左侧片段将被此新实例替换.您将观察到左侧片段将被销毁,另一个左侧片段将被创建.右侧片段没有特殊行为.
简介:创建新的父片段,创建两个新的左片段,创建新的右片段.
如果您确定在这种setRetainInstance(true)情况下,您的正确片段正在销毁而不是您的左片段,请将示例项目发布到github/etc.这证明了这一点.
更新:如果您FragmentTransaction.replace()在左侧片段上使用,为什么删除正确的片段
由于内部条件,您的代码将尝试在同一容器上替换您自己的左片段.
以下是处理替换的Android 4.1源代码的代码段:
...
case OP_REPLACE: {
Fragment f = op.fragment;
if (mManager.mAdded != null) {
for (int i=0; i<mManager.mAdded.size(); i++) {
Fragment old = mManager.mAdded.get(i);
if (FragmentManagerImpl.DEBUG) Log.v(TAG,
"OP_REPLACE: adding=" + f + " old=" + old);
if (f == null || old.mContainerId == f.mContainerId) {
if (old == f) {
op.fragment = f = null;
} else {
if (op.removed == null) {
op.removed = new ArrayList<Fragment>();
}
op.removed.add(old);
old.mNextAnim = op.exitAnim;
if (mAddToBackStack) {
old.mBackStackNesting += 1;
if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of "
+ old + " to " + old.mBackStackNesting);
}
mManager.removeFragment(old, mTransition, mTransitionStyle);
}
}
}
}
if (f != null) {
f.mNextAnim = op.enterAnim;
mManager.addFragment(f, false);
}
} break;
...
Run Code Online (Sandbox Code Playgroud)
如果您尝试用自己替换相同的片段,则有一些代码可以尝试忽略此操作:
if (old == f) {
op.fragment = f = null;
}
Run Code Online (Sandbox Code Playgroud)
由于f为null,并且我们仍在继续迭代我们的片段,这似乎具有从FragmentManager中删除每个后续片段的副作用.我不认为这是故意的,但至少可以解释为什么你的正确片段会被破坏.不使用替换/不替换相同的片段可以解决您的问题.
有趣的是,这是最近的一次更改,并且在之前版本的Android中不存在. https://github.com/android/platform_frameworks_support/commit/5506618c80a292ac275d8b0c1046b446c7f58836
错误报告:https://code.google.com/p/android/issues/detail? id = 43265
| 归档时间: |
|
| 查看次数: |
3531 次 |
| 最近记录: |