2011-03-25 67 views
27

在我不斷學習的過程(對話框這個時候),我發現這工作:AlertDialog.Builder(Context context)爲什麼只接受Activity作爲參數?

AlertDialog.Builder builder = new AlertDialog.Builder(this); 

雖然以下不工作(在與窗口管理器,$ BadTokenException運行時失敗):

AlertDialog.Builder builder = new AlertDialog.Builder(this.getApplicationContext()); 

我不明白爲什麼,因爲the constructor爲AlertDialog.Builder被定義爲接受上下文作爲一個參數,而不是活動:

公共AlertDi alog.Builder(上下文 上下文)

構造函數使用此構建器的上下文和它創建的AlertDialog構造函數 。

我錯過了什麼?

+2

其他對話框也是如此。好問題,+1 – bigstones 2011-03-25 19:10:37

+0

@bigstones我發現了另一個線程處理類似的問題,但沒有解釋:http://stackoverflow.com/questions/3968170/android-prompt-users-input-using-a-dialog – an00b 2011-03-25 19:40:52

+0

我的猜測是Builder並不只是要求一個Activity,因爲它會阻止未來的API有其他類型的可以顯示對話的上下文。 – bigstones 2011-03-25 20:21:05

回答

17

活動繼承上下文。 AlertDialog.Builder指定了一個Context參數,因爲它可以被上下文的任何一個類使用,包括一個Activity,ListActivity,Service,...(這裏有一個常見的編碼習慣 - 你可以瞭解更多關於它的知識通過閱讀Joshua Bloch的奇妙Effective Java中的Item I8(關於Interfaces和Abstract類)。

getApplicationContext()返回您的應用程序的上下文,這與您的活動上下文大體相同 - 而「大部分」是將您拋棄的內容。細節不清楚,但這是一個廣泛遇到的問題,典型的答案是使用將寫入警報到屏幕的上下文。請注意,這是而不是 getApplicationContext()返回的那個。

現在,如果你像我一樣,你可能會說「但是我在一個不能從Activity繼承的類中工作 - 這就是爲什麼我想首先使用getApplicationContext()來達到這個目的的原因 - 呃!我實際上不會那麼粗魯地說話; p ..關鍵是我也來過這裏。我修正了這樣的問題:1)問問自己:「我是否在非活動類中使用了UI AlertDialog代碼,因爲我想跨活動......或者甚至是跨ListActivities,Services ......分享它。如果沒有,嗯......你真的有代碼中的AlertDialog UI調用,你不能保證有權訪問UI(以及上下文)嗎?如果是這樣,請重新考慮您的設計。

假設你確實希望跨活動分享這個課程,答案就變得清晰了。您希望您的類由各種呼叫者是可用的,每個大概有它自己的上下文:所以調用者必須通過它的上下文到您的類作爲參數:

myClass(Context theContext, ...) { ... }

每一項活動,服務等。然後使得像這樣的呼叫:

myClass(this, ...);

眼熟?

請注意!如果您要共享代碼,則必須考慮到並行調用不同調用的可能性,以及所有的後果。這超出了我們的範圍......

玩得開心:)

+0

感謝您的回答。不幸的是,我仍然不明白爲什麼AlertDialog.Builder(Context context)只接受Activity作爲參數。你是說這個context與this.getApplicationContext()不一樣嗎?請解釋。 – an00b 2011-03-31 17:04:06

+0

是的,看起來活動上下文是應用程序上下文的超集 - 活動通過添加AlertDialog使用的那些東西來專門化應用程序上下文。僅供參考這是我基於閱讀其他人對同一問題的發現而得出的理解。我最有信心的就是fis:將活動傳遞給我的代碼。 – DJC 2011-03-31 21:05:28

+13

「清楚」的答案仍然存在問題,因爲兩個活動可能不一定只想共享相同的「類」,他們可能想共享該類的相同「實例」。如果是這樣的話,那麼你不能讓這兩個活動都用他們自己的上下文創建共享類。 Android真的是一個糟糕的設計選擇。爲什麼你會想要創建AlertDialogs,而不是讓它們彈出所有活動? iOS可以讓你從任何地方拋出UIAlertViews。 Android也應該。 – Nate 2011-08-25 07:30:44

6

AlertDialogDialog一個子類,它有一個關聯Window,它有一個關聯LayoutParams。其中一個參數是窗口的type。缺省類型是TYPE_APPLICATION_ATTACHED_DIALOG,它需要父窗口。

與Activity關聯的WindowManager被配置爲使用Activity的窗口作爲父窗口。與應用程序關聯的WindowManager沒有關聯的父窗口。

底線:要成功顯示對話框,您必須將默認窗口類型更改爲不需要父窗口的類型,或者必須使用具有關聯父窗口的上下文。

相關問題