Context-----Activity,Application之間的交流使者


      Context,我們在android開發中經常見到這個名詞,尤其是某些方法的參數列表,像是我們Toast中的makeText()中的第一個參數,就是Context。可以這么說,Context是 android中的基礎,只有切實掌握好Context的概念和用法,我們才能寫出更好的代碼。那么,現在就讓我們一起來看一下所謂的Context。

      Context,如果是直接從文檔翻譯過來,就真的是十足的專業了:提供應用環境全局信息的接口,並且這個接口是由抽象類實現的,它的執行被android系統所提供,允許我們獲取以應用為特征的資源和類型,同時啟動應用級的操作,如啟動Activity,broadcasting和接收intent。

       從這段話就可以發現,Context就是一個作為接口使用的抽象類,而且這個接口提供的是應用的全局信息,因為是android系統所提供的,所以我們大多時候都是可以直接得到的,這點會在下面講到。我們來看看它的用處,允許我們獲取以應用為特征的資源和類型,同時啟動應用級的操作。什么意思?通俗來講,就是我們可以獲取其他應用的資源和類,至於下半句的啟動應用級的操作,我們可以暫時忽略,因為不是這里的重點。

一.Context的作用

      Context的最大作用就是我們可以通過傳遞它來獲得其他Activity或Application的相關資源和方法,它就相當於它們的引用,我們通過引用來獲得對象的封裝,這也是我們面向對象的基礎,所以,我們主要利用它來加載和訪問資源。

二 .Context的類型
     Context的類型有兩種,一種是Activity-Context,另一種是Application-Activity,這兩種的區別就在於它們的生命周期不一樣,一個是隨着Activity的銷毀而銷毀,另一個是伴隨整個Application,鑒於我們以前學習java,C++這些語言的經驗,都會意識到,這些生命周期的不同可能會導致不同行為以及一些錯誤,這些都會在接下來講到,因為它們是我們使用Context必須注意的。
1.Application-Context
   這個之所以先講,是因為這個比較麻煩,在於它的獲取需要通過一些手段。
   Application-Context的生命周期是整個應用,所以,對於它的使用必須慎重,大部分情況下都要避免使用它,因為它會導致內存泄露的問題。我們先來舉個例子,如果我們現在在一個Activity中引入一個Application-Context,那么,當我們這個Activity關閉的時候,這個Application-Context是不會消失的,因為它的生命周期要比我們的Activity長,如果只是一些用來計算的數據還好,但是如果這個Context與我們的Activity的創建有關,或者與我們在Activity要銷毀的資源比如圖片資源有關,那么,問題就大條了!因為我們的Activity或圖片就不能正常銷毀,因為它與Application-Context相關聯,如果不能正常的釋放掉與它們相關的內存,就會出現所謂的內存泄露的問題。這種問題有時候是非常隱晦的,以至於我們根本無法察覺到,所以我們必須遵守相關的使用原則。
      現在我們以一個例子來示例如何獲得Application-Context。
      要想獲得Application-Context,我們可以先聲明一個Application的子類。   
class A extends Application{}

      現在,我們在這個類中添加一些東西來證明可以通過Context來獲得A的相關資源和方法。這次我們使用一個Toast。

      首先,是在我們的類A里添加以下的內容:

      String s = "hello";
      public String getString(String str){
             s = str;
             return s;
      }

      然后再在我們的Activity B中嘗試取用A的數據和方法:     

       A a = (A)getApplicationContext();
       String s = a.s;
       s = a.getString("hello word");
       Toast.makeText(this, s, Toast.LENGTH_LONG).show();

     然后我們還必須注意在我們的mainfest文件中注冊我們的application:

 <application android:name=".A"></application>

     注意,我們的mainfes始的at文件中一開pplication是沒有名字的,因為我們一般都只是啟動一個Activity,而不是一個application,所以,可以將我們這個application的名字注冊為繼承自Application的子類A,這樣才能正常顯示出一個Toast出來。如果沒有這么做,就可能報出這樣的錯誤:android.app.Application cannot be cast to A。

      在上面的例子中可以看到,通過一個Application的子類就能在我們的Activity中調用它的資源和方法,但是其實完全可以不用這樣做,聲明一個class,然后new一個實例同樣可以做到這點,但是這里只是想要大家明白,Context的確可以傳遞相關類的引用,並且通過這個引用來獲取相關類的資源和方法,而且這個Context甚至可以轉化為具體的子類,我們的getApplicationContext()返回的其實是一個Context,之所以能將它轉換為A,是因為Context傳遞的就是Application-Context,它是一個Application類型的,而類A是Application的子類,父類轉化為子類,這里就會有個疑問,就是我們的父類是不可以強制轉化為子類的,因為子類可能有父類沒有的方法,這樣的轉化就會出現問題,但是,我們也知道,可以將子類的引用轉化為父類,因為父類的引用是可以指向子類的,所以這里是想說明我們的Context真的是一個引用。

      Application-Context的生命周期為整個Application,所以如果是一些需要在整個應用期間都存在的資源,我們可以將它放進一個Application-Context中,然后通過獲取這個Context來使用它們。

2.Activity-Context
      正如上面講的一樣,這個Context的生命周期是和得到它的引用的Activity一樣長,如果這個Activity結束了,那么,這個Context也會得到釋放。它並不像我們上面的Application-Context需要特意去獲得,可以在一個Activity中使用this就可以獲得當前Activity的Context。還是拿上面例子中的Toast.makeText(this, s, Toast.LENGTH_LONG).show(),其中的this就是當前的Activity-Context,但是,一味的使用this是很危險的,我們要注意的就是,在匿名內部類如果單純只是使用this是會出錯的,因為內部類中使用this得到的是內部類的對象引用,而不是我們要得到的外部類的引用,於是,這時候就必須使用類名.this這種方式,這種做法在按鈕的事件監聽中是特別要注意的。
  3.使用規則
     因為使用Activity-Cntext會出現內存泄露的危險,所以我們一般都是使用Application-Context。下面就是這兩者的使用規則:
    (1)不要讓生命周期長的對象引用Activity-Context,保證引用要與Ativity本身生命周期是一樣的,對於生命周期長的對象,使用Application-Context 。
     如果你想要在某個Activity的界面上顯示某個組件,比如說Toast,那么,請把你的Activity的Context作為參數傳給Toast,這樣就能將你的Activity和Toast關聯起來,但是,如果你想要在一個Activity中設置好你的Toast,然后再在另一個Activity中顯示,記住,你可以有兩種選擇,一種,就是通過我們的Intent:
    
      Intent intent = new Intent(Activity1.this, Activity2.class);
      startActivity(intent);

      這個Activity1就是我們要顯示Toast的Activity,而Acticity2就是我們設置Toast的Activity。

      但是,如果想要在Activity1中調用Toast.show(),接受Activity2中返回的Toast的話,那么,使用默認的樣式是非常簡單的,如果你真的想要使用自定義的格式,自定義一個布局文件Toast.xml,那么,請在你的Activity1中寫下這幾句:
     
      LayoutInflater layout = getLayoutInflater();
      View view = layout.inflate(R.layout.toast, null);  

      記住,必須是在setContentView()之后進行切換,不然就會報錯,而且,必須是在你要顯示的Activity的setContentView(),如果你放在Activity2中的setContentView()也是會出錯,就是空指針,因為我們的layout的元素只有在setContentView()之后才開始分配內存,而且我們只是調用Activity2的方法而已,並沒有啟動Activity2,這點必須注意。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM