在我的一个应用程序中,我正在尝试实现以下逻辑:
1)在Activity的onStart()期间启动一些网络操作并添加进度片段:
@Override
protected void onStart() {
super.onStart();
refreshData();
}
private void refreshData() {
if (!isInProgress)
{
showSpinner();
}
//Do boring network request
.......
}
private void showSpinner() {
getSupportFragmentManager().beginTransaction()
.add(new ProgressFragment(), "").addToBackStack("")
.commitAllowingStateLoss();
}
private void hideSpinner() {
getSupportFragmentManager().popBackStack();
}
2)在onStop()期间 - 取消活动网络操作(如果有)并停止进度条(如果正在运行):
@Override
protected void onStop() {
if (isInProgress) {
//cancel network op
....
hideSpinner();
}
super.onStop();
}
3)在onSaveInstanceState()期间保存一些UI状态:
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
super.onSaveInstanceState(outState);
}
所以,问题是在onSaveInstanceState()
之前调用onStop()
,所以当我尝试删除进度条时 - 我得到java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
异常
显然我在Activity< - > Fragment交互中遗漏了一些基本内容,那么处理我的用例的正确方法是什么?
答案 0 :(得分:2)
总体建议是避免提交事务以响应异步事件。有关详细信息,请参阅this article。但是,有时它是不可避免的,您可以设置一些更复杂的状态检查和恢复。
对于您的特定情况(似乎您希望在活动不再可见时网络请求停止),您可以采取相应的措施:
public class SampleActivity extends FragmentActivity {
private static final String PROGRESS_FRAGMENT = "progress_fragment";
@Override
protected void onStart() {
super.onStart();
refreshData();
}
private void refreshData() {
if (!isInProgress) {
isInProgress = true;
showSpinner();
}
}
private void cancelRefresh() {
if (isInProgress) {
isInProgress = false;
//cancel request
hideSpinner();
}
}
private void showSpinner() {
getSupportFragmentManager()
.beginTransaction()
.add(new ProgressFragment(), PROGRESS_FRAGMENT)
.commit();
}
private void hideSpinner() {
FragmentManager mgr = getSupportFragmentManager();
Fragment spinner = mgr.findFragmentByTag(PROGRESS_FRAGMENT);
if (spinner != null) {
mgr.beginTransaction()
.remove(spinner)
.commit();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
cancelRefresh();
}
@Override
protected void onStop() {
super.onStop();
cancelRefresh();
}
}
由于您不知道将调用onSaveInstanceState()
,因此您可以在onSaveInstanceState()
和onStop()
上取消取消。使用标志设置和跟踪片段的标签,它只会执行一次,并且应该是安全的。
答案 1 :(得分:2)
解释此异常的原因:
我查看了KitKat源代码,看来popBackStack
使用处理程序执行其工作(将其操作排入队列):
http://androidxref.com/4.4.2_r1/xref/frameworks/base/core/java/android/app/FragmentManager.java#499
所以它将在当前事件的整个生命周期之后执行。
您可以尝试使用popBackStackImmediate,但它也会执行checkStateLoss();在刚开始的时候
http://androidxref.com/4.4.2_r1/xref/frameworks/base/core/java/android/app/FragmentManager.java#508
和checkStateLoss()检查变量mStateSaved,该变量在onSaveInstanceState中设置为true(但无法找到此源部分)。
http://androidxref.com/4.4.2_r1/xref/frameworks/base/core/java/android/app/FragmentManager.java#1321