对话框的的常见异常分析
下面分析三个异常,一句话总结:对话框show和dismss没有处理好
1. 首先说一个google api的坑:
对话框的构造参数api是context,实际上要求是一个activity。否则会报异常。
原因大概是dialog show出来,需要activity的窗口对象。
2. 对话框show了以后,如果activity被销毁后,没有调用dismiss,则会在show的代码处记录异常:the dialog has been leaked here。
一般来说,这个异常不是导致程序崩溃的直接原因,不需要解决。该日志记录的后面通常还会记录一个exception,那个才是直接的原因,才是需要解决的。
一般原因是这样的:
在正常的程序设计中,activity结束前,dialog被dimiss掉。
但是当activity在执行dismiss代码之前,异常结束(例如其他对象的空指针了),则dialog被泄露掉了。
如果解决了前面的异常(例如那个空指针),dialog自然会被正常dimiss。
3. activity ondestroy以后调用dimiss。
这里讨论的是多线程程序设计的常见缺陷。
异常栈如下:
10-29 14:39:41.554: E/AndroidRuntime(20892): java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{41b97180 V.E..... R.....I. 0,0-960,246} not attached to window manager
10-29 14:39:41.554: E/AndroidRuntime(20892): at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:379)
10-29 14:39:41.554: E/AndroidRuntime(20892): at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:308)
10-29 14:39:41.554: E/AndroidRuntime(20892): at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:109)
10-29 14:39:41.554: E/AndroidRuntime(20892): at android.app.Dialog.dismissDialog(Dialog.java:338)
10-29 14:39:41.554: E/AndroidRuntime(20892): at android.app.Dialog.dismiss(Dialog.java:321)
10-29 14:39:41.554: E/AndroidRuntime(20892): at com.example.administrator.myapplication.MainActivity$2.run(MainActivity.java:56)
下面分析三个异常,一句话总结:对话框show和dismss没有处理好
1. 首先说一个google api的坑:
对话框的构造参数api是context,实际上要求是一个activity。否则会报异常。
原因大概是dialog show出来,需要activity的窗口对象。
2. 对话框show了以后,如果activity被销毁后,没有调用dismiss,则会在show的代码处记录异常:the dialog has been leaked here。
一般来说,这个异常不是导致程序崩溃的直接原因,不需要解决。该日志记录的后面通常还会记录一个exception,那个才是直接的原因,才是需要解决的。
一般原因是这样的:
在正常的程序设计中,activity结束前,dialog被dimiss掉。
但是当activity在执行dismiss代码之前,异常结束(例如其他对象的空指针了),则dialog被泄露掉了。
如果解决了前面的异常(例如那个空指针),dialog自然会被正常dimiss。
3. activity ondestroy以后调用dimiss。
这里讨论的是多线程程序设计的常见缺陷。
异常栈如下:
10-29 14:39:41.554: E/AndroidRuntime(20892): java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{41b97180 V.E..... R.....I. 0,0-960,246} not attached to window manager
10-29 14:39:41.554: E/AndroidRuntime(20892): at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:379)
10-29 14:39:41.554: E/AndroidRuntime(20892): at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:308)
10-29 14:39:41.554: E/AndroidRuntime(20892): at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:109)
10-29 14:39:41.554: E/AndroidRuntime(20892): at android.app.Dialog.dismissDialog(Dialog.java:338)
10-29 14:39:41.554: E/AndroidRuntime(20892): at android.app.Dialog.dismiss(Dialog.java:321)
10-29 14:39:41.554: E/AndroidRuntime(20892): at com.example.administrator.myapplication.MainActivity$2.run(MainActivity.java:56)
触发代码如下:
7秒后会调用activity的finish,则该activity会被系统销毁,activity的onDestroy会随后被系统调用。
而10秒后我们才销毁dialog。
这个代码会导致crash
日志的生命周期调用如下:
常见的出问题的设计是:异步网络请求与转圈。
出错者的常规思路:
1. 请求前show dialog,转圈,作载入态。
2. 请求结束后,调用dialog的dismiss。
该思路的错误:
用户在网络情况差的情况,会提前返回,导致activity很快销毁,而dialog很长时间后才会被dismiss。
解决方案有两种:
1. 对话框显示时,activity不能被finish。
或2. onDestory时清理,调用对话框的dismiss。
日志的生命周期调用如下:
常见的出问题的设计是:异步网络请求与转圈。
出错者的常规思路:
1. 请求前show dialog,转圈,作载入态。
2. 请求结束后,调用dialog的dismiss。
该思路的错误:
用户在网络情况差的情况,会提前返回,导致activity很快销毁,而dialog很长时间后才会被dismiss。
解决方案有两种:
1. 对话框显示时,activity不能被finish。
或2. onDestory时清理,调用对话框的dismiss。
4. 调用dialog.show()方法时出现IllegalArguments异常,提示:is your activity still running.
这个通常也是多线程导致的问题。
网络线程完成工作后,想在主线程显示对话框。
如果activity正常显示,没有问题。
如果用户等不及,已经退出了activity,就会发生该异常。
解决方案:
异步工作完成后,在主线程,先检测activity是否处于onResume和onPause之间的状态,如果是,则可以显示对话框,否则就不要显示对话框了。