android - intent - getapplicationcontext




何時調用活動上下文或應用程序上下文? (5)

有很多關於這兩種情況是什麼的帖子。但我仍然沒有把它說得很對

據我了解,目前為止:每個都是它的類的一個實例,這意味著一些程序員建議您盡可能多地使用this.getApplicationContext() ,以免“洩漏”任何內存。 這是因為另一個(獲取Activity實例上下文)指向每次用戶傾斜手機或離開應用程序時被銷毀的Activity 。顯然垃圾收集器(GC)沒有捕獲並因此使用內存太多..

但是,任何人都可以拿出一些非常好的代碼示例來說明如何使用this (獲取當前Activity實例的上下文)並且應用程序上下文將是無用/錯誤的?


使用哪種上下文?

有兩種類型的上下文:

  1. 應用程序上下文與應用程序相關聯,並且在應用程序的整個生命週期中始終保持不變 - 它不會更改。 因此,如果您使用Toast,則可以使用應用程序上下文甚至活動上下文(二者),因為吐司可以從應用程序中的任何地方顯示,並且不會附加到特定的窗口。 但是有很多例外情況,例外情況是您需要使用或傳遞活動上下文。

  2. 活動上下文活動相關聯,並且可以在活動被銷毀時被銷毀 - 單個應用程序可能會有多個活動(比較可能)。 有時你絕對需要活動上下文句柄。 例如,如果您啟動新活動,則需要在其Intent中使用活動上下文,以便新活動以活動堆棧的形式與當前活動相關聯。 但是,您也可以使用應用程序的上下文來啟動新的活動,但是您需要設置標誌Intent.FLAG_ACTIVITY_NEW_TASK以將其視為新任務。

讓我們考慮一些情況:

  • MainActivity.this引用了擴展Activity類的MainActivity上下文,但基類(activity)也擴展了Context類,所以它可以用來提供活動上下文。

  • getBaseContext()提供活動上下文。

  • getApplication()提供應用程序上下文。

  • getApplicationContext()也提供應用程序上下文。

欲了解更多信息,請查看此link


getApplicationContext()幾乎總是錯誤的。 Hackborn女士 (除其他人)非常明確地表示, 只有在知道為什麼使用getApplicationContext() ,只有在需要使用getApplicationContext()時才使用getApplicationContext()

直言不諱,“一些程序員”使用getApplicationContext() (或getBaseContext()的程度較小),因為他們的Java經驗有限。 他們實現了一個內部類(例如,一個OnClickListenerButtonOnClickListener ),並且需要一個Context 。 而不是使用MyActivity.this來獲得外部類的this ,它們使用getApplicationContext()getBaseContext()來獲得一個Context對象。

當你知道你需要一個Context時,你只能使用getApplicationContext() ,因為這些東西的壽命可能比任何其他可能的Context都長。 情景包括:

  • 如果您需要綁定到本身俱有全局範圍的Context東西,請使用getApplicationContext() 。 例如,在WakefulIntentService ,我使用getApplicationContext()來為服務使用靜態WakeLock 。 由於WakeLock是靜態的,我需要一個Context來獲取PowerManager來創建它,所以使用getApplicationContext()是最安全的。

  • 如果您希望通過onRetainNonConfigurationInstance() Activity實例之間的ServiceConnection (即綁定的句柄),則在從Activity綁定到Service時使用getApplicationContext() onRetainNonConfigurationInstance() 。 Android通過這些ServiceConnections在內部跟踪綁定,並持有對創建綁定的Contexts引用。 如果您從Activity綁定,則新的Activity實例將引用ServiceConnection ,該ServiceConnection具有對舊Activity的隱式引用,並且舊Activity不能被垃圾收集。

一些開發人員將自定義的Application子類用於其自己的全局數據,它們通過getApplicationContext()檢索。 這當然是可能的。 我更喜歡靜態數據成員,如果沒有其他原因,只能有一個自定義Application對象。 我使用自定義的Application對象構建了一個應用Application並發現它很痛苦。 哈克博恩女士也贊同這一立場

以下是不管使用getApplicationContext()原因:

  • 這不是一個完整的Context ,支持Activity所做的一切。 您將嘗試使用此Context各種事情都會失敗, 主要與GUI有關

  • 如果來自getApplicationContext()Context持有由您調用創建的東西而您不清除的東西,它可以創建內存洩漏。 通過一個Activity ,如果它持有某種東西,一旦Activity被垃圾收集,其他的東西也會被刷新。 Application對像在整個過程中保持不變。


我只是使用這個表作為何時使用不同類型的Context的指導,例如Application context (即: getApplicationContext() )和活動上下文 ,還有BroadcastReceiver上下文

原文here獲取更多信息。


我想知道為什麼不為每個它支持的操作使用應用程序上下文。 最後,它降低了內存洩漏的機會,並且對getContext()或getActivity()(當使用注入的應用程序上下文或通過應用程序中的靜態方法獲取時)缺少空值檢查。 像Hackborn女士所說的僅在需要時才使用應用上下文的陳述對我而言似乎沒有說服力,沒有解釋為什麼。 但似乎我發現了一個不安的原因:

發現某些Android版本/設備組合中存在不遵循這些規則的問題。 例如,如果我有一個通過Context傳遞的BroadcastReceiver,並將該Context轉換為Application Context,然後嘗試在應用程序上下文中調用registerReceiver(),則有許多實例可以正常工作,但也有很多實例,由於ReceiverCallNotAllowedException而導致崩潰。 這些崩潰發生在從API 15到22的各種Android版本中https://possiblemobile.com/2013/06/context/#comment-2443283153

因為無法保證下表中描述為受應用程序上下文支持的所有操作都適用於所有Android設備!


當您使用Activity上下文與Application上下文時,兩個很好的例子是在顯示Toast消息或內置對話消息時使用Application上下文會導致異常:

ProgressDialog.show(this, ....);

要么

Toast t = Toast.makeText(this,....);

這兩個都需要來自Activity上下文的信息,這些信息在Application上下文中沒有提供。





android-context