06-07 02:45:20.344 E/AndroidRuntime( 2882): FATAL EXCEPTION: main
06-07 02:45:20.344 E/AndroidRuntime( 2882): java.lang.IllegalStateException: Failure saving state: ErrorDialog{41461640 #1 ErrorDialog} has target not in fragment manager: AccountCheckSettingsFragment{41461088}
06-07 02:45:20.344 E/AndroidRuntime( 2882): at android.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1609)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at android.app.Activity.onSaveInstanceState(Activity.java:1202)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at com.android.email.activity.setup.AccountSetupActivity.onSaveInstanceState(AccountSetupActivity.java:41)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at android.app.Activity.performSaveInstanceState(Activity.java:1150)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1215)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3007)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at android.app.ActivityThread.handleStopActivity(ActivityThread.java:3066)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at android.app.ActivityThread.access$900(ActivityThread.java:134)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1230)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at android.os.Handler.dispatchMessage(Handler.java:99)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at android.os.Looper.loop(Looper.java:137)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at android.app.ActivityThread.main(ActivityThread.java:4830)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at java.lang.reflect.Method.invokeNative(Native Method)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at java.lang.reflect.Method.invoke(Method.java:511)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
06-07 02:45:20.344 E/AndroidRuntime( 2882): at dalvik.system.NativeStart.main(Native Method)
06-07 02:45:20.354 W/ActivityManager( 310): Force finishing activity com.android.email/.activity.setup.AccountSetupOptions
以上异常信息,我在网上查找有 但是却没有给出解决方案 很是苦恼私下也去看了onSaveInstanceState被调用说明的官方api 但是确实不知道如何修改我跟踪到AccountSetupActivity.java的41行 调用的super.onSaveInstanceState(outState);并且查看了framework层的
android.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1609)
android.app.Activity.onSaveInstanceState(Activity.java:1202)这两个类 均是Google原生代码 无改动啊
public class AccountSetupActivity extends Activity {
private static final boolean DEBUG_SETUP_FLOWS = false; // Don't check in set to true @Override
public void onCreate(Bundle savedInstanceState) {
SetupData.restore(savedInstanceState);
super.onCreate(savedInstanceState);
if (DEBUG_SETUP_FLOWS) {
Log.d(getClass().getName(), SetupData.debugString());
}
} @Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); SetupData.save(outState);
}
}
求解决方案 及定位分析的原因 谢谢了 分数不够可以再加~Email异常
异常日志信息如下:
06-07 02:45:20.334 E/FragmentManager( 2882): Failure saving state: ErrorDialog{41461640 #1 ErrorDialog} has target not in fragment manager: AccountCheckSettingsFragment{41461088}
06-07 02:45:20.334 E/FragmentManager( 2882): Active Fragments in 4145d9d0:
06-07 02:45:20.334 E/FragmentManager( 2882): #0: null
06-07 02:45:20.334 E/FragmentManager( 2882): #1: ErrorDialog{41461640 #1 ErrorDialog}
06-07 02:45:20.334 E/FragmentManager( 2882): mFragmentId=#0 mContainerId=#0 mTag=ErrorDialog
06-07 02:45:20.334 E/FragmentManager( 2882): mState=4 mIndex=1 mWho=android:fragment:1 mBackStackNesting=0
06-07 02:45:20.334 E/FragmentManager( 2882): mAdded=true mRemoving=false mResumed=false mFromLayout=false mInLayout=false
06-07 02:45:20.334 E/FragmentManager( 2882): mHidden=false mDetached=false mMenuVisible=true mHasMenu=false
06-07 02:45:20.334 E/FragmentManager( 2882): mRetainInstance=false mRetaining=false mUserVisibleHint=true
06-07 02:45:20.334 E/FragmentManager( 2882): mFragmentManager=FragmentManager{4145d9d0 in AccountSetupBasics{4145d8a8}}
06-07 02:45:20.334 E/FragmentManager( 2882): mActivity=com.android.email.activity.setup.AccountSetupBasics@4145d8a8
06-07 02:45:20.334 E/FragmentManager( 2882): mArguments=Bundle[{ErrorDialog.Message=无法连接到服务器。, ErrorDialog.ExceptionId=1}]
06-07 02:45:20.334 E/FragmentManager( 2882): mTarget=AccountCheckSettingsFragment{41461088} mTargetRequestCode=0
提示说明ErrorDialog未与指定的FragmentManager绑定【AccountCheckSettingsFragment】而在packages\apps\Email\src\com\android\email\activity\setup\AccountCheckSettingsFragment.java中绑定ErrorDialog的代码如下 FragmentManager fm = getFragmentManager();
......
if (fm.findFragmentByTag(ErrorDialog.TAG) == null) {
ErrorDialog errorDialog = ErrorDialog.newInstance(
getActivity(), this, mProgressException);
fm.beginTransaction()
.add(errorDialog, ErrorDialog.TAG)
.commit();
}以上代码只是从FragmentManager 中去检测ErrorDialog.TAG 来判别ErrorDialog 是否存在 ,如果不存在,则添加ErrorDialog 的实例。代码如下:
public static ErrorDialog newInstance(Context context, AccountCheckSettingsFragment target,
MessagingException ex) {
ErrorDialog fragment = new ErrorDialog();
Bundle arguments = new Bundle();
arguments.putString(ARGS_MESSAGE, getErrorString(context, ex));
arguments.putInt(ARGS_EXCEPTION_ID, ex.getExceptionType());
fragment.setArguments(arguments);
fragment.setTargetFragment(target, 0);
return fragment;
}而ErrorDialog 的实例却依赖于AccountCheckSettingsFragment用户在配置邮箱信息执行Next操作时,会事先弹出检测邮箱服务器外发设置及服务器接收设置信息的Dailog、此时用户再按Home键切换到后台运行检查,中途检测时,意外断网或者网络不好的情况下会弹出ErrorDialog ,一旦出现ErrorDialog 依赖 的AccountCheckSettingsFragment 不存在的情况下【这里我们无法知道AccountCheckSettingsFragment 何时会系统被销毁】,执行绑定到FragmentManager的操作会出现以上异常。处理意见 * 在执行绑定操作时,事先判别AccountCheckSettingsFragment 在FragmentManager中查找是否存在,如果存在 则执行绑定ErrorDialog
Fragment tempFm = fm.findFragmentById(this.getId()); if ((tempFm != null) && (fm.findFragmentByTag(ErrorDialog.TAG) == null)) {
......红色部分为添加代码
1).exchange接收服务器配置界面,点击下一步后应用将向当前activity(AccountSetupExchange)安装无界面透明的账户检查fragment(AccountCheckSettingsFragment);该处理以FragmentTransaction事务形式添加,并将该事务压入目标activity的FragmentManager的后退栈中以便于用户点击back键后执行事务回滚
2).AccountCheckSettingsFragment安装后执行账户检查异常任务,该异常任务处理中将向前台抛出参数检查转圈对话框CheckingDialog示意用户参数检查情况;异步任务后台线程处理结束后将结果抛到UI主线程并随之销毁CheckingDialog
3).而在系统响应“下一步”按键启动异步任务后台处理过程中(大致100ms左右,此时CheckingDialog已安装显示),极限操作快速点击“上一步”系统响应该事件,即执行当前activity的“back”键处理,这将对activity属下的FragmentManager的后退栈做一次pop处理(移除之前压入该栈中的AccountCheckSettingsFragment事务),即卸载销毁AccountCheckSettingsFragment;与此同时,AccountCheckSettingsFragment销毁意味着账户检查结束,这将取消账户检查异常任务
4).此时即造成了异常场景:AccountCheckSettingsFragment被销毁,账户检查异常任务被取消进而导致靠异步任务post结果进行销毁CheckingDialog的流程无法执行;此时按下“home”键后将触发activity的onSaveInstanceState保存其上各种信息如fragments各种参数,进而与该activity对应的FragmentManager检查fragment数据异常:CheckingDialog存活,但是CheckingDialog的target fragment即 AccountCheckSettingsFragment已消失,抛出异常IllegalStateExceptiontempFm 偶尔为null上述场景为其一,此处POP/IMAP/Exchange类似,ErrorDialog和CheckingDialog类似,保护的话可在AccountCheckSettingsFragment的onDestroy中增加dialog的dismiss、创建dialog的地方增加tempFm的判断