posts - 8,  comments - 6,  trackbacks - 0

          1、Context概念

          其實(shí)一直想寫一篇關(guān)于Context的文章,但是又怕技術(shù)不如而誤人子弟,于是參考了些資料,今天準(zhǔn)備整理下寫出來,如有不足,請(qǐng)指出,參考資料會(huì)在醒目地方標(biāo)明。

          Context,相信不管是第一天開發(fā)Android,還是開發(fā)Android的各種老鳥,對(duì)于Context的使用一定不陌生~~你在加載資源、啟動(dòng)一個(gè)新的Activity、獲取系統(tǒng)服務(wù)、獲取內(nèi)部文件(夾)路徑、創(chuàng)建View操作時(shí)等都需要Context的參與,可見Context的常見性。大家可能會(huì)問到底什么是Context,Context字面意思上下文,或者叫做場景,也就是用戶與操作系統(tǒng)操作的一個(gè)過程,比如你打電話,場景包括電話程序?qū)?yīng)的界面,以及隱藏在背后的數(shù)據(jù);

          但是在程序的角度Context又是什么呢?在程序的角度,我們可以有比較權(quán)威的答案,Context是個(gè)抽象類,我們可以直接通過看其類結(jié)構(gòu)來說明答案:


          可以看到Activity、Service、Application都是Context的子類;

          也就是說,Android系統(tǒng)的角度來理解:Context是一個(gè)場景,代表與操作系統(tǒng)的交互的一種過程。從程序的角度上來理解:Context是個(gè)抽象類,而Activity、Service、Application等都是該類的一個(gè)實(shí)現(xiàn)。

          在仔細(xì)看一下上圖:Activity、Service、Application都是繼承自ContextWrapper,而ContextWrapper內(nèi)部會(huì)包含一個(gè)base context,由這個(gè)base context去實(shí)現(xiàn)了絕大多數(shù)的方法。

          先扯這么多,有能力了會(huì)從別的角度去審視Context,加油~


          2、Context與ApplicationContext

          看了標(biāo)題,千萬不要被誤解,ApplicationContext并沒有這個(gè)類,其實(shí)更應(yīng)該叫做:Activity與Application在作為Context時(shí)的區(qū)別。嗯,的確是這樣的,大家在需要Context的時(shí)候,如果是在Activity中,大多直接傳個(gè)this,當(dāng)在匿名內(nèi)部類的時(shí)候,因?yàn)閠his不能用,需要寫XXXActivity.this,很多哥們會(huì)偷懶,直接就來個(gè)getApplicationContext。那么大家有沒有想過,XXXActivity.this和getApplicationContext的區(qū)別呢?

          XXXActivity和getApplicationContext返回的肯定不是一個(gè)對(duì)象,一個(gè)是當(dāng)前Activity的實(shí)例,一個(gè)是項(xiàng)目的Application的實(shí)例。既然區(qū)別這么明顯,那么各自的使用場景肯定不同,亂使用可能會(huì)帶來一些問題。

          下面開始介紹在使用Context時(shí),需要注意的問題。


          3、引用的保持

          大家在編寫一些類時(shí),例如工具類,可能會(huì)編寫成單例的方式,這些工具類大多需要去訪問資源,也就說需要Context的參與。

          在這樣的情況下,就需要注意Context的引用問題。

          例如以下的寫法:

          1. package com.mooc.shader.roundimageview;  
          2.   
          3. import android.content.Context;  
          4.   
          5. public class CustomManager  
          6. {  
          7.     private static CustomManager sInstance;  
          8.     private Context mContext;  
          9.   
          10.     private CustomManager(Context context)  
          11.     {  
          12.         this.mContext = context;  
          13.     }  
          14.   
          15.     public static synchronized CustomManager getInstance(Context context)  
          16.     {  
          17.         if (sInstance == null)  
          18.         {  
          19.             sInstance = new CustomManager(context);  
          20.         }  
          21.         return sInstance;  
          22.     }  
          23.       
          24.     //some methods   
          25.     private void someOtherMethodNeedContext()  
          26.     {  
          27.           
          28.     }  
          29. }  

          對(duì)于上述的單例,大家應(yīng)該都不陌生(請(qǐng)別計(jì)較getInstance的效率問題),內(nèi)部保持了一個(gè)Context的引用;

          這么寫是沒有問題的,問題在于,這個(gè)Context哪來的我們不能確定,很大的可能性,你在某個(gè)Activity里面為了方便,直接傳了個(gè)this;這樣問題就來了,我們的這個(gè)類中的sInstance是一個(gè)static且強(qiáng)引用的,在其內(nèi)部引用了一個(gè)Activity作為Context,也就是說,我們的這個(gè)Activity只要我們的項(xiàng)目活著,就沒有辦法進(jìn)行內(nèi)存回收。而我們的Activity的生命周期肯定沒這么長,所以造成了內(nèi)存泄漏。

          那么,我們?nèi)绾尾拍鼙苊膺@樣的問題呢?

          有人會(huì)說,我們可以軟引用,嗯,軟引用,假如被回收了,你不怕NullPointException么。

          把上述代碼做下修改:

          1. public static synchronized CustomManager getInstance(Context context)  
          2.     {  
          3.         if (sInstance == null)  
          4.         {  
          5.             sInstance = new CustomManager(context.getApplicationContext());  
          6.         }  
          7.         return sInstance;  
          8.     }  

          這樣,我們就解決了內(nèi)存泄漏的問題,因?yàn)槲覀円玫氖且粋€(gè)ApplicationContext,它的生命周期和我們的單例對(duì)象一致。

          這樣的話,可能有人會(huì)說,早說嘛,那我們以后都這么用不就行了,很遺憾的說,不行。上面我們已經(jīng)說過,Context和Application Context的區(qū)別是很大的,也就是說,他們的應(yīng)用場景(你也可以認(rèn)為是能力)是不同的,并非所有Activity為Context的場景,Application Context都能搞定。

          下面就開始介紹各種Context的應(yīng)用場景。


          4、Context的應(yīng)用場景



          大家注意看到有一些NO上添加了一些數(shù)字,其實(shí)這些從能力上來說是YES,但是為什么說是NO呢?下面一個(gè)一個(gè)解釋:

          數(shù)字1:啟動(dòng)Activity在這些類中是可以的,但是需要?jiǎng)?chuàng)建一個(gè)新的task。一般情況不推薦。

          數(shù)字2:在這些類中去layout inflate是合法的,但是會(huì)使用系統(tǒng)默認(rèn)的主題樣式,如果你自定義了某些樣式可能不會(huì)被使用。

          數(shù)字3:在receiver為null時(shí)允許,在4.2或以上的版本中,用于獲取黏性廣播的當(dāng)前值。(可以無視)

          注:ContentProvider、BroadcastReceiver之所以在上述表格中,是因?yàn)樵谄鋬?nèi)部方法中都有一個(gè)context用于使用。


          好了,這里我們看下表格,重點(diǎn)看Activity和Application,可以看到,和UI相關(guān)的方法基本都不建議或者不可使用Application,并且,前三個(gè)操作基本不可能在Application中出現(xiàn)。實(shí)際上,只要把握住一點(diǎn),凡是跟UI相關(guān)的,都應(yīng)該使用Activity做為Context來處理;其他的一些操作,Service,Activity,Application等實(shí)例都可以,當(dāng)然了,注意Context引用的持有,防止內(nèi)存泄漏。


          5、總結(jié)

          好了,到此,Context的分析基本完成了,希望大家在以后的使用過程中,能夠稍微考慮下,這里使用Activity合適嗎?會(huì)不會(huì)造成內(nèi)存泄漏?這里傳入Application work嗎?

          由于參考內(nèi)容過多,本文改為譯文咯~~

          其他精彩文章文章

          Android KSOAP2調(diào)用.net webservice

          jQuery教程(8)-DOM樹操作之使用反向插入方法

          android學(xué)習(xí)筆記(34)使用AlertDialog創(chuàng)建簡單對(duì)話框

          android學(xué)習(xí)筆記(33)畫廊視圖(Gallery)的功能和用法

          android navidgation drawer 在導(dǎo)航抽屜中如何改變List選中項(xiàng)的...

          更多關(guān)于android開發(fā)文章

          posted on 2015-01-05 13:40 ♂游泳的魚 閱讀(3622) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           

          <2015年1月>
          28293031123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          留言簿(1)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          主站蜘蛛池模板: 佛学| 剑川县| 富平县| 方正县| 广灵县| 彭阳县| 乌拉特中旗| 独山县| 穆棱市| 藁城市| 石楼县| 夏津县| 易门县| 南充市| 安岳县| 修文县| 神农架林区| 洱源县| 浠水县| 灵川县| 鸡东县| 任丘市| 榆中县| 嘉黎县| 新宁县| 鹤岗市| 黄龙县| 铜鼓县| 孟连| 南川市| 前郭尔| 兴山县| 晋宁县| 涿鹿县| 建德市| 昭觉县| 华阴市| 会宁县| 五大连池市| 洪江市| 荣昌县|