Android Context 熟悉還是陌生?

一、什么是Context
二臭墨、Context的創(chuàng)建時(shí)機(jī)和獲取
  1. Context的創(chuàng)建時(shí)機(jī)
  2. Context的獲取
三、Application使用相關(guān)問(wèn)題
  1. 什么時(shí)候初始化全局變量
  2. 自定義Application膘盖?
四胧弛、Context引起的內(nèi)存泄露


Android應(yīng)用都是使用Java語(yǔ)言來(lái)編寫(xiě)的,本質(zhì)上也是一個(gè)對(duì)象衔憨,那么Activity可以new嗎叶圃?一個(gè)Android程序和一個(gè)Java程序,他們最大的區(qū)別在哪里践图?劃分界限又是什么呢掺冠?其實(shí)簡(jiǎn)單點(diǎn)分析,Android程序不像Java程序一樣,隨便創(chuàng)建一個(gè)類德崭,寫(xiě)個(gè)main()方法就能跑了斥黑,Android應(yīng)用模型是基于Activity、Service眉厨、BroadcastReceiver等組件的應(yīng)用設(shè)計(jì)模式锌奴,組件的運(yùn)行要有一個(gè)完整的Android工程環(huán)境,在這個(gè)環(huán)境下憾股,這些組件并不是像一個(gè)普通的Java對(duì)象new一下就能創(chuàng)建實(shí)例的了鹿蜀,而是要有它們各自的上下文環(huán)境Context》颍可以這樣講茴恰,Context是維持Android程序中各組件能夠正常工作的一個(gè)核心功能類。

什么是Context

一個(gè)Activity是一個(gè)Context斩熊,一個(gè)Service也是一個(gè)Context往枣。在程序中,我們把可以把Context理解為當(dāng)前對(duì)象在程序中所處的一個(gè)環(huán)境粉渠,一個(gè)與系統(tǒng)交互的過(guò)程分冈。用戶和操作系統(tǒng)的每一次交互都是一個(gè)場(chǎng)景,比如微信聊天霸株,此時(shí)的“環(huán)境”是指聊天的界面以及相關(guān)的數(shù)據(jù)請(qǐng)求與傳輸雕沉,Context在加載資源、啟動(dòng)Activity淳衙、獲取系統(tǒng)服務(wù)蘑秽、創(chuàng)建View等操作都要參與。打電話箫攀、發(fā)短信肠牲,這些都是一個(gè)有界面的場(chǎng)景,還有一些沒(méi)有界面的場(chǎng)景靴跛,比如后臺(tái)運(yùn)行的服務(wù)(Service)缀雳。一個(gè)應(yīng)用程序可以認(rèn)為是一個(gè)工作環(huán)境,用戶在這個(gè)環(huán)境中會(huì)切換到不同的場(chǎng)景梢睛,這就像一個(gè)前臺(tái)秘書(shū)肥印,她可能需要接待客人,可能要打印文件绝葡,還可能要接聽(tīng)客戶電話深碱,而這些就稱之為不同的場(chǎng)景,前臺(tái)秘書(shū)可以稱之為一個(gè)應(yīng)用程序藏畅。下面我們來(lái)看一下Context的繼承結(jié)構(gòu):


Context類敷硅,一個(gè)純Abstract類,有ContextImpl和ContextWrapper兩個(gè)實(shí)現(xiàn)類:

  • ContextWrapper包裝類
    其構(gòu)造函數(shù)中必須包含一個(gè)真正的Context引用。ContextWrapper中提供了attachBaseContext()(由系統(tǒng)調(diào)用)方法绞蹦,用于給ContextWrapper對(duì)象中指定真正的Context對(duì)象力奋,即ContextImpl對(duì)象,調(diào)用ContextWrapper的方法都會(huì)被轉(zhuǎn)向ContextImpl的方法幽七。
  • ContextImpl類
    上下文功能的實(shí)現(xiàn)類景殷。
  • ContextThemeWrapper類
    一個(gè)帶主題的封裝類,其內(nèi)部包含了與Theme相關(guān)的接口澡屡,這里所說(shuō)的主題是指在AndroidManifest.xml中通過(guò)android:theme為Application元素或者Activity元素指定的主題猿挚。當(dāng)然,只有Activity才需要主題挪蹭,Service是不需要主題的亭饵,因?yàn)镾ervice是沒(méi)有界面的后臺(tái)場(chǎng)景,所以Service直接繼承于ContextWrapper梁厉,Application同理。

總結(jié):Context的兩個(gè)子類分工明確踏兜,其中ContextImpl是Context的具體實(shí)現(xiàn)類词顾,ContextWrapper是Context的包裝類。Activity碱妆,Application肉盹,Service雖都繼承自ContextWrapper,但它們初始化的過(guò)程中都會(huì)創(chuàng)建ContextImpl對(duì)象疹尾,由ContextImpl實(shí)現(xiàn)Context中的方法上忍。
  那么,Context到底可以實(shí)現(xiàn)哪些功能呢纳本?這個(gè)就實(shí)在是太多了窍蓝,彈出Toast、啟動(dòng)Activity繁成、啟動(dòng)Service吓笙、發(fā)送廣播、操作數(shù)據(jù)庫(kù)等等都需要用到Context史汗。由于Context的具體能力是由ContextImpl類去實(shí)現(xiàn)的矩屁,因此在絕大多數(shù)場(chǎng)景下昵时,Activity、Service和Application這三種類型的Context都是可以通用的叁鉴,但在使用場(chǎng)景上是有一些規(guī)則,以下表格中列出了各Context的使用場(chǎng)景:

以上表格中NO上添加了一些數(shù)字佛寿,其實(shí)這些從能力上來(lái)說(shuō)是YES幌墓,但是為什么說(shuō)是NO呢?下面一個(gè)一個(gè)解釋:

  • NO^1:?jiǎn)?dòng)Activity在這些類中是可以的,但是需要?jiǎng)?chuàng)建一個(gè)新的task克锣。不推薦茵肃。
    如果我們用Application Context或Service Context去啟動(dòng)一個(gè)LaunchMode為standard的Activity的時(shí)候會(huì)報(bào)錯(cuò),這是因?yàn)榉茿ctivity類型的Context并沒(méi)有所謂的任務(wù)棧袭祟,所以待啟動(dòng)的Activity就找不到棧了验残。解決這個(gè)問(wèn)題的方法就是為待啟動(dòng)的Activity指定FLAG_ACTIVITY_NEW_TASK標(biāo)記位,這樣啟動(dòng)的時(shí)候就為它創(chuàng)建一個(gè)新的任務(wù)棧巾乳,而此時(shí)Activity是以singleTask模式啟動(dòng)的您没。
  • NO^2:在這些類中去layout inflate是合法的,但是會(huì)使用系統(tǒng)默認(rèn)的主題樣式胆绊,如果你自定義了某些樣式可能不會(huì)被使用氨鹏。不推薦。

所以:

  • 凡是跟UI相關(guān)的压状,都應(yīng)使用Activity做為Context來(lái)處理仆抵;其他的一些操作,Service,Activity,Application等都可以种冬,當(dāng)然得注意Context引用的持有镣丑,防止內(nèi)存泄漏。
    比如啟動(dòng)Activity娱两,還有彈出Dialog莺匠。出于安全原因的考慮,Android是不允許Activity或Dialog憑空出現(xiàn)的十兢,一個(gè)Activity的啟動(dòng)必須要建立在另一個(gè)Activity的基礎(chǔ)之上趣竣,也就是以此形成的返回棧。而Dialog則必須在一個(gè)Activity上面彈出(除非是System Alert類型的Dialog)旱物,因此在這種場(chǎng)景下遥缕,我們只能使用Activity類型的Context,否則將會(huì)出錯(cuò)异袄。

了解了Context通砍,那在一個(gè)應(yīng)用程序中,Context的數(shù)量又是多少呢烤蜕?由以上的介紹可以知道:**Context數(shù)量 = Activity數(shù)量 + Service數(shù)量 + 1 **

Context的創(chuàng)建時(shí)機(jī)和獲取

1.Context的創(chuàng)建時(shí)機(jī)

(1)創(chuàng)建Application對(duì)象的時(shí)機(jī)
  每個(gè)應(yīng)用程序在第一次啟動(dòng)時(shí)封孙,都會(huì)首先創(chuàng)建Application對(duì)象。在應(yīng)用程序啟動(dòng)一個(gè)Activity(startActivity)的流程中讽营,創(chuàng)建Application的時(shí)機(jī)是創(chuàng)建handleBindApplication()方法中虎忌,該函數(shù)位于 ActivityThread.java類中,如下:

//創(chuàng)建Application時(shí)同時(shí)創(chuàng)建的ContextIml實(shí)例
  private final void handleBindApplication(AppBindData data){
      …
      ///創(chuàng)建Application對(duì)象
      Application app = data.info.makeApplication(data.restrictedBackupMode, null);
      …
  }
  public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
      …
     try {
         java.lang.ClassLoader cl = getClassLoader();
         ContextImpl appContext = new ContextImpl();    //創(chuàng)建一個(gè)ContextImpl對(duì)象實(shí)例
         appContext.init(this, null, mActivityThread);  //初始化該ContextIml實(shí)例的相關(guān)屬性
         ///新建一個(gè)Application對(duì)象
         app = mActivityThread.mInstrumentation.newApplication(
                 cl, appClass, appContext);
        appContext.setOuterContext(app);  //將該Application實(shí)例傳遞給該ContextImpl實(shí)例
     }
     …
 }

(2)創(chuàng)建Activity對(duì)象的時(shí)機(jī)
  通過(guò)startActivity()或startActivityForResult()請(qǐng)求啟動(dòng)一個(gè)Activity時(shí)橱鹏,如果系統(tǒng)檢測(cè)需要新建一個(gè)Activity對(duì)象時(shí)膜蠢,就會(huì)回調(diào)handleLaunchActivity()方法堪藐,該方法繼而調(diào)用performLaunchActivity()方法,去創(chuàng)建一個(gè)Activity實(shí)例挑围,并且回調(diào)onCreate()礁竞,onStart()方法等, 函數(shù)都位于 ActivityThread.java類 杉辙,如下:

//創(chuàng)建一個(gè)Activity實(shí)例時(shí)同時(shí)創(chuàng)建ContextIml實(shí)例
private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
    …
    Activity a = performLaunchActivity(r, customIntent);  //啟動(dòng)一個(gè)Activity
}
private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {
    …
    Activity activity = null;
    try {
        //創(chuàng)建一個(gè)Activity對(duì)象實(shí)例
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    }
    if (activity != null) {
        ContextImpl appContext = new ContextImpl();      //創(chuàng)建一個(gè)Activity實(shí)例
        appContext.init(r.packageInfo, r.token, this);   //初始化該ContextIml實(shí)例的相關(guān)屬性
        appContext.setOuterContext(activity);            //將該Activity信息傳遞給該ContextImpl實(shí)例
        …
    }
    …
}

(3)創(chuàng)建Service對(duì)象的時(shí)機(jī)
  通過(guò)startService或者bindService時(shí)模捂,如果系統(tǒng)檢測(cè)到需要新創(chuàng)建一個(gè)Service實(shí)例,就會(huì)回調(diào)handleCreateService()方法蜘矢,完成相關(guān)數(shù)據(jù)操作狂男。handleCreateService()函數(shù)位于 ActivityThread.java類,如下:

//創(chuàng)建一個(gè)Service實(shí)例時(shí)同時(shí)創(chuàng)建ContextIml實(shí)例
private final void handleCreateService(CreateServiceData data){
    …
    //創(chuàng)建一個(gè)Service實(shí)例
    Service service = null;
    try {
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = (Service) cl.loadClass(data.info.name).newInstance();
    } catch (Exception e) {
    }
    …
    ContextImpl context = new ContextImpl(); //創(chuàng)建一個(gè)ContextImpl對(duì)象實(shí)例
    context.init(packageInfo, null, this);   //初始化該ContextIml實(shí)例的相關(guān)屬性
    //獲得我們之前創(chuàng)建的Application對(duì)象信息
    Application app = packageInfo.makeApplication(false, mInstrumentation);
    //將該Service信息傳遞給該ContextImpl實(shí)例
    context.setOuterContext(service);
    …
}

另外品腹,通過(guò)對(duì)ContextImp的分析可知岖食,其方法的大多數(shù)操作都是直接調(diào)用其屬性mPackageInfo(該屬性類型為PackageInfo)的相關(guān)方法而來(lái)。這說(shuō)明ContextImp是一種輕量級(jí)類舞吭,而PackageInfo才是真正重量級(jí)的類泡垃。而一個(gè)App里的所有ContextIml實(shí)例,都對(duì)應(yīng)同一個(gè)packageInfo對(duì)象羡鸥。

2.Context的獲取

(1)通常我們想要獲取Context對(duì)象兔毙,主要有以下四種方法

  • View.getContext,返回當(dāng)前View對(duì)象的Context對(duì)象兄春,通常是當(dāng)前正在展示的Activity對(duì)象
  • Activity.getApplicationContext,獲取的context來(lái)自允許在應(yīng)用(進(jìn)程)application中的所有Activity锡溯,當(dāng)你需要用到的Context超出當(dāng)前Activity的生命周期時(shí)使用
  • Activity.this 返回當(dāng)前的Activity實(shí)例赶舆,如果是UI控件需要使用Activity作為Context對(duì)象,但是默認(rèn)的Toast實(shí)際上使用ApplicationContext也可以
  • ContextWrapper.getBaseContext()用來(lái)獲取一個(gè)ContextWrapper進(jìn)行裝飾之前的Context祭饭,也就是ContextImpl對(duì)象芜茵,如果想獲取另一個(gè)可以訪問(wèn)的application里面的Context時(shí)可以使用

(2)再來(lái)看看getApplication()和getApplicationContext()
  這兩個(gè)方法有什么區(qū)別呢?看看以下結(jié)果:

通過(guò)上面的代碼倡蝙,可以看到它們是同一個(gè)對(duì)象九串。其實(shí)這個(gè)結(jié)果也很好理解,因?yàn)榍懊嬉呀?jīng)說(shuō)過(guò)了寺鸥,Application本身就是一個(gè)Context猪钮,所以這里獲取getApplicationContext()得到的結(jié)果就是Application本身的實(shí)例。那么問(wèn)題來(lái)了胆建,既然這兩個(gè)方法得到的結(jié)果都是相同的烤低,那么Android為什么要提供兩個(gè)功能重復(fù)的方法呢?實(shí)際上這兩個(gè)方法在作用域上有比較大的區(qū)別笆载。
  getApplication()方法的語(yǔ)義性非常強(qiáng)扑馁,一看就知道是用來(lái)獲取Application實(shí)例的涯呻,但這個(gè)方法只有在Activity和Service中才能調(diào)用。如果在一些其它的場(chǎng)景腻要,比如BroadcastReceiver中也想獲得Application的實(shí)例复罐,這時(shí)就需要借助getApplicationContext()方法了。也就是說(shuō)雄家,getApplicationContext()方法的作用域會(huì)更廣一些效诅,任何一個(gè)Context的實(shí)例,只要調(diào)用getApplicationContext()方法都可以拿到我們的Application對(duì)象咳短。
(3)getActivity()和getContext()

  • getActivity()返回Activity填帽,getContext()返回Context;
  • 兩者是Fragment的方法咙好,但Activity沒(méi)有篡腌,多數(shù)情況下兩者沒(méi)有什么區(qū)別,但新版Support Library包勾效,F(xiàn)ragment不被Activity持有時(shí)嘹悼,區(qū)別見(jiàn)這里
  • 參數(shù)是context的层宫,可以使用getActivity() 杨伙。因?yàn)锳ctivity間接繼承了Context,但Context不是Activity萌腿;
  • this和getContext() 并不是完全相同限匣。在Activity類中可以使用this,因?yàn)锳ctivity繼承自Context毁菱,但是getContext()方法不在Activity類中米死。

Application使用相關(guān)問(wèn)題

1.什么時(shí)候初始化全局變量

在應(yīng)用程序中常常會(huì)持有一個(gè)自己的Application,首先讓它繼承自系統(tǒng)的Application類贮庞,然后在自己的Application類中去封裝一些通用的操作峦筒。雖然Application的用法很簡(jiǎn)單,但同時(shí)也存在著不少Application誤用的場(chǎng)景窗慎。Application是Context的其中一種類型物喷,那么是否就意味著,只要是Application的實(shí)例遮斥,就能隨時(shí)使用Context的各種方法呢峦失?做個(gè)實(shí)驗(yàn)試:

方式1:
public class MyApplication extends Application {      
    public MyApplication() {  
        String packageName = getPackageName();  
        Log.d("TAG", "package name is " + packageName);  
    }     
}  
  
方式2:
public class MyApplication extends Application {      
    @Override  
    public void onCreate() {  
        super.onCreate();  
        String packageName = getPackageName();  
        Log.d("TAG", "package name is " + packageName);  
    }     
} 

這是一個(gè)非常簡(jiǎn)單的自定義Application,以上我們分別采用了在MyApplication的構(gòu)造方法和onCreate()方法中兩種方式來(lái)獲取當(dāng)前應(yīng)用程序的包名伏伐,并打印出來(lái)宠进。獲取包名使用了getPackageName()方法,這個(gè)方法就是由Context提供的藐翎。那哪種方式能得到想要的結(jié)果呢材蹬?得到的結(jié)果是否又是一樣实幕?
結(jié)果表明,方式一應(yīng)用程序一啟動(dòng)就立刻崩潰了堤器,報(bào)的是一個(gè)空指針異常:


方式二運(yùn)行正常:


這兩個(gè)方法之間到底發(fā)生了什么事情呢昆庇?我們重新回顧一下ContextWrapper類的源碼,ContextWrapper中有一個(gè)attachBaseContext()方法闸溃,這個(gè)方法會(huì)將傳入的一個(gè)Context參數(shù)賦值給mBase對(duì)象整吆,之后mBase對(duì)象就有值了。而我們又知道辉川,所有Context的方法都是調(diào)用這個(gè)mBase對(duì)象的同名方法表蝙,那么也就是說(shuō)如果在mBase對(duì)象還沒(méi)賦值的情況下就去調(diào)用Context中的任何一個(gè)方法時(shí),就會(huì)出現(xiàn)空指針異常乓旗,上面的代碼就是這種情況府蛇。
Application中方法的執(zhí)行順序?yàn)椋篈pplication構(gòu)造方法—>attachBaseContext()—>onCreate()。
Application中在onCreate()方法里去初始化各種全局變量數(shù)據(jù)是一種比較推薦的做法屿愚,但如果你想把初始化的時(shí)間提前到極致汇跨,也可以重寫(xiě)attachBaseContext(),如下所示:

public class MyApplication extends Application {      
    @Override  
    protected void attachBaseContext(Context base) {  
        // 在這里調(diào)用Context的方法會(huì)崩潰  
        super.attachBaseContext(base);  
        // 在這里可以正常調(diào)用Context的方法  
    }       
} 
2.自定義Application妆距?

其實(shí)Android官方并不太推薦我們使用自定義的Application穷遂,基本上只有需要做一些全局初始化的時(shí)候可能才需要用到自定義Application。多數(shù)項(xiàng)目只是把自定義Application當(dāng)成了一個(gè)通用工具類娱据,而這個(gè)功能并不需要借助Application來(lái)實(shí)現(xiàn)蚪黑,使用單例可能是一種更加標(biāo)準(zhǔn)的方式。不過(guò)自定義Application也并沒(méi)有什么副作用中剩,它和單例模式二選一都可以實(shí)現(xiàn)同樣的功能祠锣,但把自定義Application和單例模式混合到一起使用,就會(huì)出各種問(wèn)題了咽安。如下:


public class MyApplication extends Application {  
      
    private static MyApplication app;  
      
    public static MyApplication getInstance() {  
        if (app == null) {  
            app = new MyApplication();  
        }  
        return app;  
    }       
} 

就像單例模式一樣,這里提供了一個(gè)getInstance()方法蓬推,用于獲取MyApplication的實(shí)例妆棒,有了這個(gè)實(shí)例之后,就可以調(diào)用MyApplication中的各種工具方法了沸伏,然而事實(shí)卻非想的那么美好糕珊。因?yàn)槲覀冎繟pplication是屬于系統(tǒng)組件,系統(tǒng)組件的實(shí)例是要由系統(tǒng)來(lái)去創(chuàng)建的毅糟,如果這里我們自己去new一個(gè)MyApplication的實(shí)例红选,它就只是一個(gè)普通的Java對(duì)象而已,而不具備任何Context的能力姆另,如果想通過(guò)該對(duì)象來(lái)進(jìn)行Context操作喇肋,就會(huì)發(fā)生空指針錯(cuò)誤坟乾。那么如果真的想要提供一個(gè)獲取MyApplication實(shí)例的方法,比較標(biāo)準(zhǔn)的寫(xiě)法又是什么樣的呢蝶防?其實(shí)這里我們只需謹(jǐn)記一點(diǎn)甚侣,Application全局只有一個(gè),它本身就已經(jīng)是單例了间学,無(wú)需再用單例模式去為它做多重實(shí)例保護(hù)了殷费,代碼如下所示:

public class MyApplication extends Application {      
    private static MyApplication app;  
      
    public static MyApplication getInstance() {  
        return app;  
    }  
      
    @Override  
    public void onCreate() {  
        super.onCreate();  
        app = this;  
    }      
}  

getInstance()方法可以照常提供,但是里面不要做任何邏輯判斷低葫,直接返回app對(duì)象就可以了详羡,而app對(duì)象又是什么呢?在onCreate()方法中我們將app對(duì)象賦值成this嘿悬,this就是當(dāng)前Application的實(shí)例实柠,那么app也就是當(dāng)前Application的實(shí)例了。

Context引起的內(nèi)存泄露

context發(fā)生內(nèi)存泄露的話鹊漠,就會(huì)泄露很多內(nèi)存主到。這里泄露的意思是gc沒(méi)有辦法回收activity的內(nèi)存,在傳遞Context時(shí)會(huì)增加對(duì)象指針的引用計(jì)數(shù)躯概,所以基于智能指針技術(shù)的GC無(wú)法釋放相應(yīng)的內(nèi)存登钥。
  當(dāng)屏幕旋轉(zhuǎn)的時(shí)候,系統(tǒng)會(huì)銷毀當(dāng)前的activity娶靡,保存狀態(tài)信息牧牢,再創(chuàng)建一個(gè)新的。比如我們寫(xiě)了一個(gè)應(yīng)用程序姿锭,它需要加載一個(gè)很大的圖片塔鳍,我們不希望每次旋轉(zhuǎn)屏幕的時(shí)候都銷毀這個(gè)圖片,重新加載呻此。實(shí)現(xiàn)這個(gè)要求的簡(jiǎn)單想法就是定義一個(gè)靜態(tài)的Drawable轮纫,這樣Activity 類創(chuàng)建銷毀它始終保存在內(nèi)存中。實(shí)現(xiàn)類似:

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

這段程序看起來(lái)很簡(jiǎn)單焚鲜,但是卻問(wèn)題很大掌唾。當(dāng)屏幕旋轉(zhuǎn)的時(shí)候會(huì)有內(nèi)存泄漏(即gc沒(méi)法銷毀Activity)。屏幕旋轉(zhuǎn)的時(shí)系統(tǒng)會(huì)銷毀當(dāng)前的activity忿磅,但是當(dāng)drawable和view關(guān)聯(lián)后糯彬,drawable保存了view的 reference,即sDrawable保存了textView的引用葱她,而textView保存了Activity的引用撩扒。既然Drawable不能銷毀,它所引用和間接引用的都不能銷毀吨些,這樣系統(tǒng)就沒(méi)有辦法銷毀當(dāng)前的Activity搓谆,于是造成了內(nèi)存泄露炒辉,gc對(duì)這種類型的內(nèi)存泄露是無(wú)能為力的。為了防止內(nèi)存泄露挽拔,我們應(yīng)該注意以下幾點(diǎn):

  • 不要讓生命周期長(zhǎng)的對(duì)象引用Activity Context辆脸,即保證引用activity的對(duì)象要與activity本身生命周期是一樣的
  • 對(duì)于生命周期長(zhǎng)的對(duì)象,可以使用Application Context
  • 避免非靜態(tài)的內(nèi)部類螃诅,盡量使用靜態(tài)類啡氢,避免生命周期問(wèn)題,注意內(nèi)部類對(duì)外部對(duì)象引用導(dǎo)致的生命周期變化
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末术裸,一起剝皮案震驚了整個(gè)濱河市倘是,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌袭艺,老刑警劉巖搀崭,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異猾编,居然都是意外死亡瘤睹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)答倡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)轰传,“玉大人,你說(shuō)我怎么就攤上這事瘪撇』癫纾” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵倔既,是天一觀的道長(zhǎng)恕曲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)渤涌,這世上最難降的妖魔是什么佩谣? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮实蓬,結(jié)果婚禮上稿存,老公的妹妹穿的比我還像新娘。我一直安慰自己瞳秽,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布率翅。 她就那樣靜靜地躺著练俐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪冕臭。 梳的紋絲不亂的頭發(fā)上腺晾,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天燕锥,我揣著相機(jī)與錄音,去河邊找鬼悯蝉。 笑死归形,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鼻由。 我是一名探鬼主播暇榴,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蕉世!你這毒婦竟也來(lái)了蔼紧?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤狠轻,失蹤者是張志新(化名)和其女友劉穎奸例,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體向楼,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡查吊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了湖蜕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逻卖。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖重荠,靈堂內(nèi)的尸體忽然破棺而出箭阶,到底是詐尸還是另有隱情,我是刑警寧澤戈鲁,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布仇参,位于F島的核電站,受9級(jí)特大地震影響婆殿,放射性物質(zhì)發(fā)生泄漏诈乒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一婆芦、第九天 我趴在偏房一處隱蔽的房頂上張望怕磨。 院中可真熱鬧,春花似錦消约、人聲如沸肠鲫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)导饲。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渣锦,已是汗流浹背硝岗。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留袋毙,地道東北人型檀。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像听盖,于是被迫代替她去往敵國(guó)和親胀溺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容