Android中Context

來源:互聯網
上載者:User

近期學習Android,看到文章對Context的講解比較少,所以上網查了下,還可以。

Context字面意思上下文,位於framework package的android.content.Context中,其實該類為LONG型,類似Win32中的Handle控制代碼,很多方法需要通過 Context才能識別調用者的執行個體,比如說Toast的第一個參數就是Context,一般在Activity中我們直接用this代替,代表調用者的 執行個體為Activity,而到了一個button的onClick(View view)等方法時,我們用this時就會報錯,所以我們可能使用ActivityName.this來解決,主要原因是因為實現Context的類主要有Android特有的幾個模型,Activity、Service以及BroadcastReceiver。

Context提供了關於應用環境全域資訊的介面。它是一個抽象類別,它的執行被Android系統所提供。它允許擷取以應用為特徵的資源和類型。同時啟動應用級的操作,如啟動Activity,broadcasting和接收intents。

  兩種類型的Context在android中context可以作很多操作,但是最主要的功能是載入和訪問資源。在android中有兩種context,一種是 application context,一種是activity context,通常我們在各種類和方法間傳遞的是activity context。比如一個activity的onCreate

protected void onCreate(Bundle state) {
super.onCreate(state);
 
TextView label = new TextView(this);
//傳遞context給view control

label.setText("Leaks are bad");
 
setContentView(label);
}

把activity context傳遞給view,意味著view擁有一個指向activity的引用,進而引用activity佔有的資源:view hierachy, resource等。  記憶體泄露這樣如果context發生記憶體泄露的話,就會泄露很多記憶體。這裡泄露的意思是gc沒有辦法回收activity的記憶體。 注釋:為什麼GC沒有辦法回收相應的記憶體,個人感覺是因為傳遞Context會增加對象指標的引用計數,所以基於智能指標技術的GC無法釋放相應的記憶體。 當旋轉螢幕的時候,系統會銷毀當前的activity,儲存狀態資訊,再建立一個新的。比如我們寫了一個應用程式,它需要載入一個很大的圖片,我們不希望每次旋轉螢幕的時候都銷毀這個圖片,重新載入。實現這個要求的簡單想法就是定義一個靜態Drawable,這樣Activity 類建立銷毀它始終儲存在記憶體中。實作類別似:

 

public class myactivity extends Activity {
private static Drawable sBackground;
protected void onCreate(Bundle state) {
super.onCreate(state);
 
TextView label = new TextView(this);
label.setText("Leaks are bad");
 
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);//drawable attached to a view

setContentView(label);
}
}

 

這段程式看起來很簡單,但是卻問題很大。當旋轉螢幕的時候會有leak(即gc沒法銷毀activity)。我們剛才說過,旋轉螢幕的時候系統會銷毀當前的activity。但是當drawable和view關聯後,drawable儲存了view的 reference,即sBackground儲存了label的引用,而label儲存了activity的引用。既然drawable不能銷毀,它所引用和間接引用的都不能銷毀,這樣系統就沒有辦法銷毀當前的activity,於是造成了記憶體泄露。gc對這種類型的記憶體泄露是無能為力的。避免這種記憶體泄露的方法是避免activity中的任何對象的生命週期長過activity,避免由於對象對
activity的引用導致activity不能正常被銷毀。  為了防止記憶體泄露,我們應該注意以下幾點:
  1. 不要讓生命週期長的對象引用activity context,即保證引用activity的對象要與activity本身生命週期是一樣的
  2. 對於生命週期長的對象,可以使用application context
  3. 避免非靜態內部類,盡量使用靜態類,避免生命週期問題,注意內部類對外部對象引用導致的生命週期變化
application context我們可以使用application context。application context伴隨application的一生,與activity的生命週期無關。application context可以通過Context.getApplicationContext或者Activity.getApplication方法擷取。而製造Application context的方法在這裡可以找到http://stackoverflow.com/questions/708012/android-how-to-declare-global-variables/708317#708317 Java裡面通常是用一個static的變數(例如singleton之類的)來同步activity之間(程式裡面類之間)的狀態。在android裡面比較靠譜的做法是用application context來關聯這些狀態。每個activity都是context,裡麵包含了運行時的狀態。同樣application也有一個context,android會保證這個context是唯一的執行個體。做一個你自己的application context需要繼承android.app.Application,然後在app的manifest裡面說明這個類。android會自動幫你建立你這個類的執行個體,接著你用Context.getApplicationContext()方法就能在各個activity裡面獲得這個application context了。

 class MyApp extends Application {

  private String myState;

  public String getState(){
    return myState;
  }
  public void setState(String s){
    myState = s;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    ...
    MyApp appState = ((MyApp)getApplicationContext());
    String state = appState.getState();
    ...
  }

下面介紹Context的一些get方法,通過這些get方法可以擷取應用環境全域資訊:

1.public abstract Context getApplicationContext ()

Return the context of the single, global Application object of the current process.

2.public abstract ApplicationInfo getApplicationInfo ()

Return the full application info for this context's package.

3.public abstract ContentResolver getContentResolver ()

Return a ContentResolver instance for your application's package.

4.public abstract PackageManager getPackageManager ()

Return PackageManager instance to find global package information.

5.public abstract String getPackageName ()

Return the name of this application's package.

6.public abstract Resources getResources ()

Return a Resources instance for your application's package.

7.public abstract SharedPreferences getSharedPreferences (String name, int mode)

Retrieve and hold the contents of the preferences file 'name', returning a SharedPreferences through which you can retrieve and modify its values. Only one instance of the SharedPreferences object is returned to any callers for the same name, meaning they
will see each other's edits as soon as they are made.

8.public final String getString (int resId)

Return a localized string from the application's package's default string table.

9.public abstract Object getSystemService (String name)

Return the handle to a system-level service by name. The class of the returned object varies by the requested name. Currently available names are:

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.