天天看點

Context源碼分析

Context是什麼?

Context的字面意思是“上下文”,那麼這個“上下文”到底指的是什麼?“上”指的是什麼?“下”指定的是什麼?

個人的了解,有助于自己的了解的方式,不一定對,如果有更好的看法可以一塊交流學習。個人的了解,“上”指的是在APP啟動的時候,就與Context有關了,這個時候還是系統啟動階段,就與Context發生了聯系。

“下”指定的是在APP界面正常顯示出來以後,正常與使用者互動的過程中,可以用Context擷取資源,系統服務等。是以Context所謂的上下文就是承上啟下的作用。

  1. Context的類的繼承關系

    從上圖可以看到,Context隻有一個實作類ContextImpl,Application,Service,Activity都是直接或者間接繼承了ContextWrapper,ContextWrapper中有一個變量mBase,也是個Context類型,實際是ContextImpl的對象,Application,Service,Activity所有的操作都是委托給了mBase實作。

  2. Context既然是承上啟下,是個上下文,和APP啟動流程有關,先來看看系統的啟動流程和APP的啟動流程,都在一張圖裡,如下:

從上圖可以看到:

  • 首先系統的第一個程序 init跑起來,作一些初始化相關的工作,然後通過系統調用fork出了一個zygote程序,init程序通過poll阻塞在那了。
  • zygote程序被init程序fork出來以後,做一些jni初始化等,通過調用fork出了一個SystemServer程序,SystemServer程序裡面跑的都是安卓的系統服務,zygote通過jni調用java的代碼,fork出了SystemServer程序,打開了java世界的大門,自己通過sokcet監聽阻塞在那了,監聽來自socket的資訊。
  • SystemServer程序被fork出來以後,裡面會開啟非常多的系統服務,比如AMS,PMS,WMS等,SystemServer程序是一個非常重要的程序,系統的很多重要的服務都駐留在此程序中,SystemServer程序是通過Handler機制阻塞在那了。等待發來的消息并處理消息。這樣整個系統就啟動了。
  • 在PMS中,會啟動Lanuher APP,使用者就可以看到安卓系統桌面了。如果使用者點選了桌面上的QQ圖示,Lannuher程序就會通過binder機制與AMS通信,告訴AMS要啟動QQ應用,AMS收到 Lanuher程序發來的消息以後,通過socket發送資訊給zygote程序,我們知道zygote程序在fork出了SystemServer程序以後就一直在監聽着socket,是以zygote程序收到SystemServer程序發來的消息後,如果沒有建立過QQ程序,這個時候,zygote就會調用fork系統調用建立一個新的程序,用來跑QQ代碼,這個程序就是QQ程序,QQ App程序建立以後第一個調用的就是Activity.main()方法,如上圖。

Context有什麼作用?

1 通路目前應用的資源

  • getResources
  • getAssets

2 啟動其它元件

  • Activity
  • Service

3 擷取系統服務

  • getSystemService

Application對象的ContextImpl對象建立過程

1 通過上面的系統啟動流程和APP啟動流程分析可知:第一個APP應用都是由AMS通過binder機制建立一個新的程序,然後調用ActivityThread類中的main方法開始的。很多人可能會感到奇怪為啥Android也是基于Java實作的,為啥沒有看到main方法呢?其實整個App應用的入口就是ActivityThread.main方法.所有有關Application, Activity,Service的建立都是在ActivityThread類中,其實該類就是我們App的主線程。在ActivityThread中有一個方法 performLaunchActivity()方法,在這個方法裡面就建立了Application,Activity。我們看一下這個方法。

如下圖

調用mInstrumentation.newActivity()方法建立Activity。newActivity代碼如下圖

可以看到,建立Activity以後,調用了Activity的attach方法,第一個參數就是context,在這裡Activity就和context發生了聯系,這個context其實就是ContextImpl的執行個體。接着上面的第一張圖 performLaunchActivity繼續往下走,如下圖:

通過上圖可以看到,在建立完了activity,并且調用了activity.attach()方法之後,開始建立Application對象,如下

Application app = r.packageInfo.makeApplication(false,mInstrumentation)      

makeApplication代碼如下:

随後又建立了一個ContextImpl的執行個體,代碼如下

//建立ContextImpl執行個體ContextImpl appContext = new ContextImpl();//初始化ContextImpl執行個體appContext.init(this,null,mActivityThread);//把appContext傳給了newApplication方法app = mActivityThread.mInstrumentation.newApplication(cl,appClass,appContext);//與Application發生聯系,ContextImpl執行個體儲存了Application的執行個體appappContext.setOuterContext(app);

mActivityThread.mAllApplication.add(app);
mApplication = app;      

下面看下newApplicaiton()方法,代碼如下:

static public Application newApplication(Class<?> clazz,Context context){    //通過反射建立Application執行個體
    Application app = (Application)clazz.newInstance();    //把上面傳進來的ContextImpl執行個體通過attach方法儲存了起來
    app.attach(context);    //傳回Application執行個體
    return app;
}      

建立完Application并且通過調用application執行個體的attach方法與ContextImpl執行個體發生了聯系,接下來就應該調用application的onCreate()方法了。代碼如下:

public void callApplicationOnCreate(Application app){    //調用Application的onCreate方法
    app.onCreate();
}      

建立了activity,也建立了application并且調用了application的attach和onCreate方法,接下來應該調用activity的onCreate方法了。還是在performLanucherActivity方法中。如下圖:

如上圖,通過mInstructation的callActivityOnCreate()方法調用activity的onCreate()。這段代碼和調用application的onCreate()方法的邏輯類似,自己可以看一下。這裡不再帖出代碼

*** 通過上面的分析可以知道,Context是什麼時候建立的,是怎麼建立的,何時初始化的,如何與Application和Activity發生聯系的等 ***

Application的生命周期為什麼這麼長?

我們知道,Application的生命周期是和APP程序一樣長的,Application對應的context也是一樣,為什麼Application的生命周期為什麼這麼長?

Context的用法注意

繼續閱讀