先看一下Context源碼,代碼以下:java
/** * Interface to global information about an application environment. This is * an abstract class whose implementation is provided by * the Android system. It * allows access to application-specific resources and classes, as well as * up-calls for application-level operations such as launching activities, * broadcasting and receiving intents, etc. */ public abstract class Context { ... }
解釋以下:面試
下面看看Context的實現類ContextImpl源碼註釋:app
/** * Common implementation of Context API, which provides the base * context object for Activity and other application components. */ class ContextImpl extends Context { ... }
解釋以下:ide
再來看看Context的包裝類ContextWrapper源碼註釋:this
/** * Proxying implementation of Context that simply delegates all of its calls to * another Context. Can be subclassed to modify behavior without changing * the original Context. */ public class ContextWrapper extends Context { Context mBase; ... }
解釋以下:代理
代理Context的實現,簡單地將其全部調用委託給另外一個Context。能夠進行子類化以修改行爲而不更改原始上下文。code
該類包括了一個真正的Context對象,也就是ContextImpl。其是ContextImpl的代理模式。component
面試最常問的就是一個應用有多少個Context,有多少個Window。
Android應用程序只有四大組件,經過源碼,咱們看出,只有Activity和Service是繼承了Context的。固然,每一個應用還有額外的一個Application。因此總數爲:orm
APP:Context = Application(1) + Activity(number) + Service(number);
首先,確定有人問爲何context是在ActivityThread中實例化的,這邊不具體深刻啓動流程。有興趣的能夠本身去看。對象
經過startActivity咱們會啓動一個新的Activity。它最終會調用ActivityThread的performLaunchActivity方法,具體以下:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... ContextImpl appContext = createBaseContextForActivity(r); ... try { Application app = r.packageInfo.makeApplication(false, mInstrumentation); if (activity != null) { ... appContext.setOuterContext(activity); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback); ... } ... } ... return activity; }
上述代碼差很少就是經過createBaseContextForActivity(r);建立appContext,而後經過activity.attach設置。如今咱們看看createBaseContextForActivity的源碼:
private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) { ... ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token); appContext.setOuterContext(activity); Context baseContext = appContext; ...... return baseContext; }
能夠看到是經過ContextImpl去建立一個activity的上下文,而後經過setOuterContext去將當前的activty和context進行綁定。
在來看看attach方法:
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback) { attachBaseContext(context); ... }
經過上述代碼,咱們能夠看出經過ContextThemeWrapper類的attachBaseContext方法,將createBaseContextForActivity中實例化的ContextImpl對象傳入到ContextWrapper類的mBase變量,這樣ContextWrapper(Context子類)類的成員mBase就被實例化爲Context的實現類ContextImpl。
經過startService或者bindService咱們會啓動一個新的Service。它最終會調用ActivityThread的handleCreateService方法,具體以下:
private void handleCreateService(CreateServiceData data) { ...... Service service = null; try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance(); } catch (Exception e) { ...... } try { ...... ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); Application app = packageInfo.makeApplication(false, mInstrumentation); service.attach(context, this, data.info.name, data.token, app,ActivityManagerNative.getDefault()); service.onCreate(); ...... } catch (Exception e) { ...... } }
具體和上面的activity類型,這邊不深刻,咱們看看service的attach方法:
public final void attach( Context context, ActivityThread thread, String className, IBinder token, Application application, Object activityManager) { attachBaseContext(context); ..... }
能夠看出步驟流程和Activity的相似,只是實現細節略有不一樣而已。
前面咱們說到一個應用有一個Application,它的生命週期伴隨着整個項目。建立Application的過程也是在ActivityThread中的handleBindApplication方法中操做。Application的建立是在該方法中調運LoadedApk類的makeApplication方法中實現,LoadedApk類的makeApplication()方法中源代碼以下:
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { ... try { java.lang.ClassLoader cl = getClassLoader(); ContextImpl appContext = new ContextImpl(); appContext.init(this, null, mActivityThread); app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); appContext.setOuterContext(app); } ... }
能夠看出它將appContext經過Instrumentation的newApplication傳進去了,下面咱們看看Instrumentation的newApplication方法:
public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return newApplication(cl.loadClass(className), context); } static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { ...... app.attach(context); return app; }
咱們接着看Application的attach方法:
final void attach(Context context) { attachBaseContext(context); ...... }
能夠看出,和activity與service相似,只是實現的細節變了。
不少人分不清getApplication和getApplicationContext,這其中包括我,因而就去翻了翻源碼:
public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2, Window.OnWindowDismissedCallback { ...... public final Application getApplication() { return mApplication; } ...... } class ContextImpl extends Context { ...... @Override public Context getApplicationContext() { return (mPackageInfo != null) ? mPackageInfo.getApplication() : mMainThread.getApplication(); } ...... }
能夠看到getApplicationContext方法是Context的方法,並且返回值是Context類型,返回對象和上面經過Service或者Activity的getApplication返回的是一個對象。
因此說對於客戶化的第三方應用來講兩個方法返回值同樣,只是返回值類型不一樣,還有就是依附的對象不一樣而已。
從上面咱們分析了context,但咱們要合理的利用的context對象,context與其所關聯的對象生命週期相同,因此咱們須要避免出現沒有必要的內存泄漏。