屏幕旋转后获取当前片段时遇到问题。
我有一个同步服务,它向MainActivity
报告进度,如果该片段当前已提交,则反过来将数据传递给SyncFragment
。
但是,如果在同步过程中旋转了屏幕,则getSupportFragmentManager().findFragmentById(R.id.crossfade_content)
返回 null,即使 SyncFragment 仍已提交且可见,并且 MainActivity 无法向 SyncFragment 报告任何进度,并且即使同步已完成,屏幕也只是卡在加载时。
我想避免使用android:configChanges
因为它应该是最后的手段,我不想将它用于一个可能导致我进一步出现问题的小问题。
这就是过程的样子
首先提交同步片段,然后从那里启动同步服务。
getSupportFragmentManager().beginTransaction()
.replace(R.id.crossfade_content, SyncFragment.newInstance(true))
.commit();
然后,同步服务向 MainActivity 报告,如果它当前处于活动状态,则会将报告转换为 SyncFragment。
@Override
public void onReceiveResult(int resultCode, Bundle resultData)
{
//…
//Report progress to SyncFragment if it is active
Fragment fragment = getCurrentFragment();
if (getCurrentFragment() instanceof SyncFragment)
{
SyncFragment syncFragment = (SyncFragment)fragment;
syncFragment.reportSyncProgress(resultCode, resultData);
}
}
在同步过程中,用户会旋转屏幕,同步片段仍然可见并处于加载模式。
@Override
public void onReceiveResult(int resultCode, Bundle resultData)
{
//…
//Report progress to SyncFragment if it is active
Fragment fragment = getCurrentFragment(); // <-- This is now returning null
if (getCurrentFragment() instanceof SyncFragment)
{
SyncFragment syncFragment = (SyncFragment)fragment;
syncFragment.reportSyncProgress(resultCode, resultData);
}
}
由于getCurrentFragment()
现在返回 null,因此即使数据可见,也无法再将数据传递到片段,并且现在卡在加载时。
编辑 - 进一步研究
因此,当屏幕旋转时,MainActivity onCreate被正常调用。在onCreate
中调用getCurrentFragment()
将如您所期望的那样返回 SyncFragment,因为该片段仍在提交。
但是,在onReceiveResult
中(在 onCreate 之后调用),相同的函数 (getCurrentFragment()
) 返回 null。
此外,当屏幕旋转时,onAttachFragment
确实会被调用,并且 SyncFragment 会像预期的那样传递给该函数。但是,由于某种原因,如果我在屏幕旋转后使用该片段的引用,则会出现片段未附加到上下文的错误。
编辑 - 更多
如果我将getCurrentFragment()
放在按钮单击上并在屏幕旋转后单击它,它会返回同步片段。只有在 onActivityResult 中,该方法才返回 null。
当屏幕方向发生变化时,现有活动将被销毁,并在之后重新创建。如果你想保留一个片段,你可以在你的片段的onCreate中使用以下代码,那么即使在方向发生变化之后,你也会得到它的实例:
setRetainInstance(true);
问题是 ResultReceiver。
重新创建活动后,ResultReceiver 无法正确报告,因此解决方案是保存其状态。
回顾我的问题,这不是一个明显的解决方案,但如果某个孤独的流浪者遇到与我相同的问题,那么这就是解决方案。
保存屏幕方向更改时的结果接收器的状态。
@Override
protected void onSaveInstanceState(Bundle outState)
{
//…
outState.putParcelable("receiver", _syncReceiver);
super.onSaveInstanceState(outState);
}
在创建时再次加载它
if (savedInstanceState != null)
_syncReceiver = savedInstanceState.getParcelable("receiver");
if (_syncReceiver == null)
_syncReceiver = new SyncResultReceiver(new Handler());
_syncReceiver.setReceiver(this);