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