Android開發經常需要使用Context來啟動Activity,或者打開SharedPreferences,或者構建一個Dialog。最近老是用到getContext(),getApplicationContext(),this等,來獲取Context,故寫此文來理清思路。確定好需要Contex ...
Android開發經常需要使用Context來啟動Activity,或者打開SharedPreferences,或者構建一個Dialog。最近老是用到getContext(),getApplicationContext(),this等,來獲取Context,故寫此文來理清思路。確定好需要Context的時候,究竟用哪個函數。
Context
什麼是Context呢?
個人的理解是:Context就是上下文,換句話說就是運行的環境。它可以用來新建對象,訪問資源。
官方的參考文檔,只有一段:
Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.
這麼一段說了3件事情(簡單的翻譯如下):
- 它是獲取應用環境信息的介面。
- 它是一個抽象類,實現由安卓系統提供。
- 它允許訪問application-specific的資源和類;執行應用級別的操作,比如開啟一個activity。
獲取Context的方法
獲取Context的方法有如下幾種:
- Activity類中使用this關鍵字
- SomeActivity.this
- 在Fragment中,可以getActivity()
- getContext()
- getApplicationContext()
- getBaseContext()
那麼這幾種獲取Context對象的方式有什麼異同?
首先將這些方法分類,按照使用的地方分類:
在Activity中可以使用的:
- Activity類中使用this關鍵字
- SomeActivity.this
- getApplicationContext()
- getBaseContext()
在Fragment中可以使用的:
- getContext()
- getActivity()
在View中可以使用的:
- getContext()
它們各自的含義
在Activity類中使用this關鍵字,等同於SomeActivity.this。
getApplicationContext() 獲取整個應用的Context,獲取的對象存活周期和應用一樣長。
getContext() View中獲取的是當前活動的Activity,Fragment中返回與之關聯的Context
getActivity() 返回當前Fragment相關聯的Activity
getBaseContext() 獲取ContextWrapper的原始context
不管是Application,還是Activity,它們都繼承了Context。
避免Context引起的記憶體泄漏
由Context引起的記憶體泄漏主要由兩個原因:
- 引用了這個Context的對象存活時間長過傳入的activity。
- 成員內部類和匿名內部類隱式持有外部類的對象導致。
第一種情況好理解,當activity銷毀的時候,還有對象引用了這個activity,那麼GC不會回收這個activity。
第二種情況的原因,參見鏈接4。講的主要是內部類會隱式的持有外部類的對象導致GC不回收這個activity。在安卓中可能發生記憶體泄漏的地方是,一個activity裡面有一個Runnable的運行還沒結束,這個activity已經銷毀了。但是這個activity被Runnabl隱式地持有,導致activity無法被回收。
既然如此,那就乾脆不要用this好了!用getApplicationContext()不就好了?
但是,getApplicationContext()有其弊端!
鏈接3解釋了不用getApplicationContext()的原因:它不是完整的Context。可能導致一些GUI相關的問題。比如AlertDialog.Builder不能使用getApplicationContext(),因為dialog需要一些主題相關的信息,而Application並不包含這些信息。(You need to use a Theme.AppCompat theme (or descendant) with this activity)
那麼什麼時候用getApplicationContext(),什麼時候用this?
一般而言,如果context不需要ui相關的操作,就用getApplicationContext()。如果對象存活時間可能比activity長,考慮使用getApplicationContext()。其他情況,確保activity銷毀前,取消引用activity,用this就好了。
參考鏈接
- https://stackoverflow.com/questions/10641144/difference-between-getcontext-getapplicationcontext-getbasecontext-and#
- https://juejin.im/post/58cb97e1128fe1006c84aafe
- https://stackoverflow.com/questions/7298731/when-to-call-activity-context-or-application-context
- https://blog.csdn.net/leunging/article/details/53080863