onSaveInstanceState 显示后无法执行此操作
Posted
技术标签:
【中文标题】onSaveInstanceState 显示后无法执行此操作【英文标题】:Can not perform this action after onSaveInstanceState show 【发布时间】:2017-06-21 17:39:15 【问题描述】:我收到以下崩溃报告:
致命异常:java.lang.IllegalStateException:无法执行此操作 onSaveInstanceState 之后的操作 在 android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1832) 在 android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1850) 在 android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:643) 在 android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:603) 在 android.support.v4.app.DialogFragment.show(DialogFragment.java:143)
以下代码导致崩溃,为了清楚起见,我删除了一些琐碎的设置代码。我已经阅读了这个错误,据我了解,.show()
在onClick()
等用户交互中应该是安全的。我唯一能想到的是query()
需要很长时间并且用户换掉了。这是对这个错误的合理解释吗?即使使用大型数据库,它在我的设备上也是即时的。还有其他可能吗?谢谢!
foldersButton.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
final List<String> paths = new ArrayList<>();
try(Cursor c = getActivity().getContentResolver().query(Meta.CONTENT_URI,
new String[]"DISTINCT " + Meta.PARENT, null, null,
Meta.PARENT + " ASC"))
while (c != null && c.moveToNext())
String path = c.getString(c.getColumnIndex(Meta.PARENT));
// We place the excluded folders at the end
if (!mExcludedFolders.contains(path))
paths.add(path);
[setup...]
int[] position = new int[2];
foldersButton.getLocationOnScreen(position);
FolderDialog dialog = FolderDialog.newInstance(
paths.toArray(new String[paths.size()]),
visible,
excluded,
position[0],
position[1]);
dialog.setStyle(DialogFragment.STYLE_NO_TITLE, R.style.FolderDialog);
[setup...]
dialog.show(getFragmentManager(), TAG);
);
【问题讨论】:
你找到解决这个致命异常的方法了吗? 【参考方案1】:如果您的此代码在活动中,请将对show
的调用包装为:
if(!isDestroyed() && !isFinishing())
如果此代码在片段中,则将调用包装到 show
中:
if (isResumed() && !isRemoving())
这或多或少会解决在不一致的 UI 状态下登陆的问题
【讨论】:
如果活动刚刚停止但没有被破坏,这将不起作用。【参考方案2】:您可以在查询执行之前显示一个进度对话框,让用户在屏幕上等待,同时通知他正在处理某些事情。
或者,如果您不想在这种情况下通知用户有关处理的信息,请检查活动是否仅在前台显示,然后显示对话框。
您可以使用一个布尔变量isInForeground
并分别在onResume
和onPause
中设置/重置它。
@Override
protected void onPause()
super.onPause();
isInForeground=false;
@Override
protected void onResume()
super.onResume();
isInForeground=true;
然后在if条件中包装对话框显示逻辑
if(isInForeground)
dialog.show(getFragmentManager(), TAG);
【讨论】:
【参考方案3】:我越看它就越困扰我,我在 UI 代码中有一个查询。这可能是我测试这个概念的初始代码,当它起作用时我不小心离开了它。
有一个LoaderManager
用于使用错误查询的应用程序,但我使用现有的onLoadFinished
来触发异步查询,该查询将在对数据库进行任何更改时更新路径结构。现在,当用户单击对话框时,该对话框已准备就绪。
由于我无法重现该错误,因此需要一周左右的时间才能对此做出判断,但无论哪种方式,之前的代码都很草率。
【讨论】:
【参考方案4】:您的活动似乎已暂停/您的应用不在前台。您可以在添加片段之前做一件事 检查您的活动是否未销毁/完成并且您的应用程序是否处于前台(未最小化)
if(!isDestroyed()&&!isFinishing()&&isAppInForground(this))
//add your fragment
编写代码检查您的应用是否在前台
/**
*
* @param context
* @return boolean
* tells whether user is currently viewing app or not if not return false otherwise true
*/
public static boolean isAppInForground(Context context)
boolean isInForeground = false;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses)
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)
for (String activeProcess : processInfo.pkgList)
if (activeProcess.equals(context.getPackageName()))
isInForeground = true;
return isInForeground;
【讨论】:
以上是关于onSaveInstanceState 显示后无法执行此操作的主要内容,如果未能解决你的问题,请参考以下文章
java.lang.IllegalStateException(onSaveInstanceState 后无法执行此操作)
在 DialogFragment 上的 onSaveInstanceState 后无法执行此操作
出现异常“IllegalStateException:onSaveInstanceState 后无法执行此操作”
异常 java.lang.IllegalStateException:onSaveInstanceState 后无法执行此操作
java.lang.IllegalStateException:onSaveInstanceState 后无法执行此操作
java.lang.IllegalStateException:onSaveInstanceState 后无法执行此操作