1. 程式人生 > >關於Android中Dialog show跟dismiss時出現crash的解決辦法

關於Android中Dialog show跟dismiss時出現crash的解決辦法

        最近在做專案的時候,越來越多的開發者反饋SDK Dialog的show以及dismiss導致程式crash,出現的問題是傳遞進來的Activity被finish或者重建(橫豎屏切換)了。下面分別對這兩種情況說明以及解決辦法。

在Dialog.show時出現crash

日誌資訊:

06-03 17:18:14.550: E/AndroidRuntime(12584): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] is not valid; is your activity running?
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at android.view.ViewRootImpl.setView(ViewRootImpl.java:587)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:326)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at android.view.Window$LocalWindowManager.addView(Window.java:561)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at android.app.Dialog.show(Dialog.java:293)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at com.umeng.socialize.controller.impl.m.onStart(SocialServiceImpl.java:1451)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at com.umeng.socialize.controller.impl.aa.onStart(SocialServiceImpl.java:2529)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at com.umeng.socialize.controller.impl.ab.onStart(SocialServiceImpl.java:2557)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at com.umeng.socialize.controller.impl.c.c(SocialServiceImpl.java:2594)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at com.umeng.socialize.controller.impl.c.doOauthVerify(SocialServiceImpl.java:2339)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at com.umeng.socialize.controller.impl.c.c(SocialServiceImpl.java:1456)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	at com.umeng.socialize.controller.impl.c.postShare(SocialServiceImpl.java:1295)
06-03 17:18:14.550: E/AndroidRuntime(12584): 	... 17 more

我們知道所有的視窗建立和管理都是依附於window manager的,因此Dialog的建立也不例外。Dialog的建立流程通過檢視原始碼可以知道,在Dialog的建構函式中,建立了一個Window物件,但我們知道Window物件並不是用於顯示的,真正用於顯示的是View物件。因此通過Dialog的show方法構造了一個mDecor的View物件,並最終通過WindowManager的addView()方法顯示Dialog,如果此時你的activity應為某種原因被finish或者重建就會出現此問題。

解決辦法:

在建立Dialog的時候,我們設定該dialog屬於某個activity,這樣我們根據Activity的狀態決定是否顯示Dialog.

建立Dialog時設定activity:

<pre name="code" class="java" style="color: rgb(51, 51, 51); font-size: 14px; line-height: 26px;">ProgressDialog <span style="font-family: 微軟雅黑;">mDialog = new ProgressDialog(this);</span>
<span style="font-family: 微軟雅黑;">mDialog.setMessage("test");</span>
mDialog.setCancelable(false);mDialog.setOwnerActivity(this); 顯示Dialog的時候做相應地判斷:
if ( mDialog != null ) {
    Activity activity = mDialog.getOwnerActivity();
    if ( activity != null && !activity.isFinishing() ) {
        mDialog.show();
    }
}

Dialog.dismiss時出現crash

日誌資訊:

06-03 21:03:18.027: E/AndroidRuntime(6197): java.lang.IllegalArgumentException: View not attached to window manager
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:385)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:287)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:79)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at android.app.Dialog.dismissDialog(Dialog.java:323)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at android.app.Dialog.dismiss(Dialog.java:306)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at com.umeng.soexample.MainActivity$1$1.onComplete(MainActivity.java:61)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at com.umeng.socialize.qq.controller.impl.UMQQSsoHandler$4.onCancel(UMQQSsoHandler.java:355)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at com.tencent.jsutil.PackIUiListener$1.handleMessage(ProGuard:29)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at android.os.Handler.dispatchMessage(Handler.java:99)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at android.os.Looper.loop(Looper.java:153)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at android.app.ActivityThread.main(ActivityThread.java:5297)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at java.lang.reflect.Method.invokeNative(Native Method)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at java.lang.reflect.Method.invoke(Method.java:511)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
06-03 21:03:18.027: E/AndroidRuntime(6197): 	at dalvik.system.NativeStart.main(Native Method)
原因:Dialog在dismiss得時候是通過直接從WindowManager remove操作來完成的。當Activity被銷燬後,此時的Dialog處於遊離狀態,在remove的時候會迭代,如果發現此View沒有在陣列mViews中時講丟擲IllegalArgumentException("View not attached to window manager")異常。

解決辦法:

建立Dialog的時候設定該Dialog所屬的Activity,在dismiss的時候根據此activity的狀態來決定是否dismiss此dialog

if ( mDialog != null && mDialog.isShowing()) {
    Activity activity = mDialog.getOwnerActivity();
    if ( activity != null && !activity.isFinishing()) {
        mDialog.dismiss();    
    }
}
上面的方法適用於在非自己的Activity中顯示Dialog的處理策略。對於自己的Activity可以直接根據Activity的生命週期方法對Dialog做相應的處理,比如在onDestroy時先dismiss此Dialog;同時可以使用Activity中對Dialog的相關回調來處理,比如Activity.showDialog方法,這樣就將此Dialog跟Activity的生命週期方法關聯起來了,在觸發onDestroy的時候自動的先關閉目前屬於此Activity且處於顯示狀態的所有Dialog。

相關推薦

關於AndroidDialog showdismiss出現crash解決辦法

        最近在做專案的時候,越來越多的開發者反饋SDK Dialog的show以及dismiss導致程式crash,出現的問題是傳遞進來的Activity被finish或者重建(橫豎屏切換)了。下面分別對這兩種情況說明以及解決辦法。 在Dialog.show時出現c

iOS 12.1 UITabbar從二級頁面pop出現偏移解決辦法

問題描述 在iOS12.1中,當UITabbar的translucent屬性為YES時,push viewController時設定控制器hidesBottomBarWhenPushed = YES會出現此問題。 問題討論 討論詳情見 此處 解決辦法 自定義UITabba

1. [轉] 命令列裡 pip list 執行出現DEPRECATION 解決辦法

[轉]命令列裡 pip list 執行時出現DEPRECATION 解決辦法 報錯內容: DEPRECATION: The default format will switch to columns in the future. You can use –format=(legacy|c

MySQL建立外來鍵出現error121解決辦法

環境:MySQL Server 5.5 + Navicat for Mysql 10.0 問題:建立外來鍵時出現121錯誤  解決:把外來鍵名改為其他名字 錯誤資訊參考: error121 這是外關鍵字名字重複的錯誤,即使是在不同的表中,外關鍵字的名字也不能重複。  er

DataGrid儲存資料出現錯誤解決辦法.

解決辦法:前臺設定DataGridDataKeyField="ID"錯誤提示:Server Error in '/News' Application. Index was out of range. Must be non-negative and

npm安裝出現錯誤解決辦法及mac下升級node.js

npm error  cwd.process 關閉所有terminal終端,執行下面的命令: $ sudo npm cache clean -f $ sudo npm install -g n n是用來管理node.js版本的。 mac 升級 node.js 的簡易方法。

mysql客戶端操作需要顯示或輸入中文出現亂碼——解決辦法

文章源:http://www.cnblogs.com/sunzn/archive/2013/03/14/2960248.html            http://www.jb51.net/article/75889.htm 在MySQL的dos客戶端輸出視窗中查詢表中的

解決Android dialog含有edittext, dismiss軟鍵盤不會自動消失的問題

解決方案:重寫dialog類中dismiss方法:public class CustomDialog extends Dialog { protected CustomDialog(Context context) { super(context);

(OK) Android Studio 3.2 建立新的AVD,出現錯誤(No space left on device)—— on Fedora 27

To install:- Google APIs Intel x86 Atom System Image (system-images;android-27;google_apis;x86)Preparing "Install Google APIs Intel x86 At

[轉] linux下shell使用上下鍵翻出歷史命名出現^[[A^[[A^[[A^[[B^[[B的問題解決,Linux使用退格鍵出現^H解決方法

XA TP brk 因此 上下 參數 csdn def 無法 [From] https://www.zmrbk.com/post-2030.html https://blog.csdn.net/suifengshiyu/article/details/40952771

Android當資料庫需要更新我們該怎麼辦

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Eclipse執行Maven打包編譯出現:Perhaps you are running on a JRE rather than a JDK?

出現錯誤後,查看了許多網友的解決方式,但都沒有解決我遇到的問題,可能是情況還是有些許的不同;下面直接說說我的問題的解決辦法,希望對大家有所幫助;Eclipse中Maven報錯資訊如下: 本以為可能是Eclipse配置Maven沒配置好,或者是jdk和jre環境出現問題,後來在cmd視窗找到

android studio提交到開源git出現:fatal: refusing to merge unrelated histories的解決辦法

android studio提交到開源git時出現:fatal: refusing to merge unrelated histories的解決辦法 1.cmd進入專案的根目錄。 2.執行下面的命令:git pull origin master –allow-unrela

解決android使用adb工具push檔案出現read-only

已開通新的部落格,後續文字都會發到新部落格 http://www.0xfree.top --- 經常在使用除錯手機或者往手機裡傳輸檔案是,會用到adb工具 adb push hostfile targetfile 但是有時會遇到這樣的問題:failed to copy hostf

關於PCL使用八叉樹出現無法解析的外部命令的錯誤*

關於PCL中使用八叉樹時出現無法解析的外部命令的錯誤 #前幾天在使用八叉樹的時候在編譯時總是出現無法解析的外部命令的錯誤 6 error LNK2001: 無法解析的外部符號 "protected: virtual bool __thiscall pcl::oc

vue引入本地swf檔案出現的路徑錯誤問題

    這幾天改一個老的政府專案。裡面用到了flash動畫,這個之前沒有接觸過,以為路徑就和普通的圖片引入一樣。 就這樣寫了: 但是這樣發現一個問題,就是在頁面上確實會顯示讓你啟用flash控制元件,但是點開後會發現一片空白。 一開始我以為是swf檔案的問題,但是在一個簡單的

MATLABimshow()函式處理影象出現全白顯示的原因

1、uint8(無符8位)與double     double函式只是將讀入影象的uint8資料轉換為double型別,一般不使用;常用的是im2double函式,將uint8影象轉為double型別,範圍為0-1,如果是255的影象,那麼255轉為1,0還是0,中間的做相

android 讀寫xml檔案取得路徑的方法/data/sdcard/src

  package com.eboy.readwritexml; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream;

警惕 MySql 更新 sql 的 WHERE 從句的 IN() 子查詢出現的效能陷阱

mer_stage 表有 216423 條記錄,DDL:CREATE TABLE `mer_stage` ( `STAGE_ID` int(11) NOT NULL AUTO_INCREMENT, `MER_ID` int(11) NOT NULL, `MER_C

關於AndroidDialog位置的設定

* lp.x與lp.y表示相對於原始位置的偏移. * 當引數值包含Gravity.LEFT時,對話框出現在左邊,所以lp.x就表示相對左邊的偏移,負值無效. * 當引數值包含Gravity.RIGHT時,對話框出現在右邊,所以lp.x就表示相對右邊的偏移,負值