Android各種獲取Context方法

Android各種獲取Context方法

首先講一講這四個函數的區別,後面還有我對context的一些理解

區別如下所示:

原文鏈接http://stackoverflow.com/questions/6854265/getapplicationcontext-getbasecontext-getapplication-getparent

翻譯+我的總結如下

1. getApplicationContext() :

這個函數返回的這個Application的上下文,所以是與app掛鉤的,所以在整個生命週期裏面都是不變的,這個好理解,但是使用的時候要注意,該context是和引用的生命週期一致的,所以和activity生命週期掛鉤的任務不要使用該context,比如網絡訪問,防止內存泄露

2. getBasecontext():

stackoverflow上面寫的是,這個函數不應該被使用,用Context代替,而Context是與activity相關連,所以當activity死亡後可能會被destroyed,我舉個我自己寫的例子

public Dialog displayDialog(int choice) { 
    switch(choice){ 
    case 0
      AlertDialog aDialog = new AlertDialog.Builder(this
      .setIcon(R.drawable.ic_launcher) 
      .setTitle("Hello World"
      .setPositiveButton("OK", new DialogInterface.OnClickListener() { 
   
      @Override 
      public void onClick(DialogInterface arg0, int arg1) { 
        Toast.makeText(getBaseContext(), "OK clicked", Toast.LENGTH_SHORT).show(); 
      } 
    });
  }
}

  

這個例子中的getBaseContext()就不能被this代替,因爲上面的this返回的是這個activity的context,而在這個onClick函數中如果使用this的話,則返回的是這個AlertDialog的context,所以要使用的是當前activity名.this 去使用,比如當前activity爲 TestActivity,那麼在裏面就是用TestActivity.this即可

 3. getApplication():

getApplication只能被Activity和Services使用,雖然在現在的Android的實現中,getApplication和getApplicationContext返回一樣的對象,但也不能保證這兩個函數一樣(例如在特殊的提供者來說),所以如果你想得到你在Manifest文件裏面註冊的App class,你不要去調用getApplicationContext,以爲你可能得不到你所要的app實例(你顯然有測試框架的經驗)。。。。

翻譯完成,一目瞭然(哪裏翻譯錯誤,請指出,水B一隻),原文:

getApplication() is available to Activity and Services only. Although in current Android Activity and Service implementations, getApplication() and getApplicationContext() return the same object, there is no guarantee that this will always be the case (for example, in a specific vendor implementation). So if you want the Application class you registered in the Manifest, you should never call getApplicationContext() and cast it to your application, because it may not be the application instance (which you obviously experienced with the test framework).

4. getParent() :

返回activity的上下文,如果這個子視圖的話,換句話說,就是當在子視圖裏面調用的話就返回一個帶有子視圖的activity對象,一目瞭然。。。

5.getActivity():

在fragment中使用,返回該fragment所依附的activity上下文

6.this

記住Activity,Service類,Application類是繼承自Context類的,所以在有的時候需要上下文,只需要使用this關鍵字即可,但是有的時候再線程裏面,this關鍵字的意義就改變了,但這個時候如果需要上下文,則需要使用 類名.this,這樣就可以了

這裏有點注意的:

做項目時遇見的,提一下吧,動態註冊廣播,在調用registerBroadcast函數的時候,需要傳入一個上下文和broadcastReceiver,查看源碼可以知道,存儲的時候context是作爲一個key的作用,所以使用同一個context來註冊同一個廣播,onreceive只會調用一次,但是如果使用不同的context,則會調用多次,雖然不調用unregisterBroadcast有時也沒事,不會報錯,但是一定不要忘記取消註銷

後續:爲了簡化context的使用方法,現在有這麼一種方法,就是在Application類裏面維護一個弱引用:

1
2
3
4
/** 用來保存當前該Application的context */ 
private static Context instance; 
/** 用來保存最新打開頁面的context */ 
private volatile static WeakReference<Context> instanceRef = null;

再寫一個方法,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static Context getInstance(){ 
        if (instanceRef == null || instanceRef.get() == null){ 
            synchronized (RootApplication.class) { 
                if (instanceRef == null || instanceRef.get() == null) { 
                    Context context = ActivityManager.getInstance().getActivity(); 
                    if (context != null
                        instanceRef = new WeakReference<>(context); 
                    else 
                        instanceRef = new WeakReference<>(instance); 
                        L.w("請確保RootActivity調用setInstanceRef方法"); 
                    
                
            
        
        return instanceRef.get(); 
    

  

最後在應用的Activity基類中(這個應該有的吧)加上兩個語句:

1
2
3
4
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    RootApplication.setInstanceRef(this); 
1
2
3
4
5
protected void onResume() { 
    super.onResume(); 
    //也要在onresume函數裏面進行設置,保證弱引用一直引用當前的可見頁面 
    RootApplication.setInstanceRef(this); 

  

這樣每次調用application的getInstance()方法一定能夠返回一個context,而且是當前唯一可見activity的context,其他地方就可以直接使用了,不用到處傳遞context,再此處統一維護即可,

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章