共计 9898 个字符,预计需要花费 25 分钟才能阅读完成。
PS:本文系转载文章,浏览原文可读性会更好,文章开端有原文链接
文章珍藏的好句子:真正的顺其自然,是竭尽所能后的不强求,而不是两手一摊的不作为。
ps:本篇文章的源码是基于 Android Api 26 来剖析的。
看到文章题目是不是有点理不清,是不是感觉笔者不晓得问啥?有点搞不懂没关系,咱们当初来一步一步地剖析;先列举一下目录;
目录
1、getString(@StringRes int resId) 办法
1、1 Application 的 getString(@StringRes int resId) 办法 | |
1、2 Activity 的 getString(@StringRes int resId) 办法 | |
1、3 Service 的 getString(@StringRes int resId) 办法 |
2、mBase 变量
2、1 Application 的 mBase 变量是什么 | |
2、2 Activity 的 mBase 变量是什么 | |
2、3 Service 的 mBase 变量是什么 | |
1、getString(@StringRes int resId) 办法
1、1 Application 的 getString(@StringRes int resId) 办法
咱们在理论开发安卓中,有时候用到 Application、Activity 和 Service 的 getString(@StringRes int resId) 办法,它们都是通过 Resources 的 getString(@StringRes int resId) 办法实现的,然而它们通过哪个对象来获取到 Resources 呢?咱们先看看 Application 的 getString(@StringRes int resId) 办法,因为 Application 继承于 ContextWrapper,ContextWrapper 又继承于 Context,所以 Application 的 getStri-ng(@StringRes int resId) 办法在 Context 中;
@NonNull | |
public final String getString(@StringRes int resId) { | |
//1、return getResources().getString(resId); | |
} | |
看正文 1 的 getResources 办法,是一个形象办法,具体实现在 ContextWrapper 类中;
@Override | |
public Resources getResources() { | |
//2、return mBase.getResources();} | |
看正文 2,Application 的 mBase 是什么呢?咱们这里保留悬念,前面剖析。
1、2 Activity 的 getString(@StringRes int resId) 办法
Activity 的 getString(@StringRes int resId) 办法跟 Application 的 get-String(@StringRes int resId) 办法剖析是一样的,这里就不再持续剖析 Activity 的了。
1、3 Service 的 getString(@StringRes int resId) 办法
Service 的 getString(@StringRes int resId) 办法跟 Application 的 get-String(@StringRes int resId) 办法剖析是一样的,这里就不再持续剖析 Service 的了。
2、mBase 变量
2、1 Application 的 mBase 变量是什么
咱们晓得,ActivityThread 是程序入口类,每个应用程序都对应着一个 ApplicationThread 对象,它是一个 Binder 对象,是 ActivityThread 的外部类,他的作用是接管 ActivityManagerService 传来的近程音讯,假如咱们第一次启动 App,ActivityManagerService 就会发来了一个 startActivity 的音讯,ActivityThread 的外部类 ApplicationThread 中的 scheduleLaunchActivity 办法(该办法有很多个参数我就不写进去了,具体看我上面贴出来的代码)就会被掉用到;
@Override | |
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, | |
ActivityInfo info, Configuration curConfig, Configuration overrideConfig, | |
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, | |
int procState, Bundle state, PersistableBundle persistentState, | |
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, | |
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) { | |
...... | |
//3、sendMessage(H.LAUNCH_ACTIVITY, r); | |
} | |
看正文 3 的代码,这里发送一个 H.LAUNCH_ACTIVITY 标记的信息,这时候 ActivityThread 的外部类 H 就会解决音讯;
private class H extends Handler {
...... | |
public void handleMessage(Message msg) { | |
...... | |
switch (msg.what) { | |
case LAUNCH_ACTIVITY: {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); | |
final ActivityClientRecord r = (ActivityClientRecord) msg.obj; | |
r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo); | |
//4、handleLaunchActivity(r, null, "LAUNCH_ACTIVITY"); | |
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); | |
} break; | |
...... | |
} | |
...... |
}
看正文 4 的代码,这里调用了 ActivityThread 的 handleLaunch-Activity(ActivityClientRecord r, Intent customIntent, String reason) 办法;
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { | |
...... | |
//5、Activity a = performLaunchActivity(r, customIntent); | |
...... | |
} | |
看正文 5 的代码,这里是创立 Activity 的办法,往下跟踪 Activity 的 performLaunchActivity(ActivityClientRecord r, Intent customIntent) 办法看看;
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); | |
...... | |
//6、ContextImpl appContext = createBaseContextForActivity(r); | |
Activity activity = null; | |
...... | |
try { | |
//7、Application app = r.packageInfo.makeApplication(false, mInstrumentation); | |
...... | |
if (activity != null) { | |
...... | |
//8、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); | |
...... | |
} | |
...... | |
} catch (SuperNotCalledException e) {throw e;} catch (Exception e) {if (!mInstrumentation.onException(activity, e)) { | |
throw new RuntimeException( | |
"Unable to start activity" + component | |
+ ":" + e.toString(), e); | |
} | |
} | |
return activity; |
}
看正文 7 的代码,r.packageInfo 是 LoadedApk 类型的对象,LoadedApk 的 makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) 办法是实现创立一个 Application 对象;
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) { | |
...... | |
Application app = null; | |
...... | |
try { | |
...... | |
//9、ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); | |
//10、app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext); | |
appContext.setOuterContext(app); | |
} catch (Exception e) {......} | |
...... | |
return app; |
}
看正文 9 的代码,ContextImpl 继承于 Context,咱们看一下 ContextImpl 的具体实现类(也就是 ContextImpl 的子类)的创立过程,也就是 Context-Impl 的 createAppContext(ActivityThread mainThread, LoadedApk packageInfo) 办法;
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo"); | |
//11、ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0, | |
null); | |
context.setResources(packageInfo.getResources()); | |
return context; |
}
从正文 11 的代码能够看出,ContextImpl 的具体实现类还是它本人;好,咱们回到正文 10 出的代码,mActivityThread.mInstrumentation 示意 Instrumentation 类型的对象,这里用 ContextImpl 对象作为其中的一个参数参数调用 Instrumentation 的 newApplication(ClassLoader cl, String className, Context context) 办法;
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException, | |
ClassNotFoundException { | |
//12、return newApplication(cl.loadClass(className), context); | |
} | |
看正文 12 的代码,Instrumentation 的 newApplication(ClassLoader cl, String className, Context context) 办法又调用 Instrumentation 的 newApplication(Class<?> clazz, Context context) 办法;
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException, | |
ClassNotFoundException {Application app = (Application)clazz.newInstance(); | |
//13、app.attach(context); | |
return app; | |
} | |
看正文 13 的代码,Instrumentation 的 newApplication(Class<?> clazz, Context context) 办法调用 Application 的 attach(Context context) 办法;
/ package / final void attach(Context context) {
//14、attachBaseContext(context); | |
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo; | |
} | |
看正文 14 的代码,Application 的 attach(Context context) 办法调用了 ContextWrapper 的 attachBaseContext(Context base) 办法(因为 Application 继承于 ContextWrapper);
protected void attachBaseContext(Context base) {
if (mBase != null) {throw new IllegalStateException("Base context already set"); | |
} | |
mBase = base; |
}
看到了吧,正文 11 处的代码初始化的 ContextImpl 对象被赋值给了 Application 的 mBase 变量,由此可见 Application 的 mBase 变量实质上是 ContextImpl 对象。
2、2 Activity 的 mBase 变量是什么
回到正文 6 的代码,也就是 ActivityThread 的 createBaseContextFor-Activity(ActivityClientRecord r) 办法;
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
...... | |
//15、ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig); | |
...... | |
return appContext; | |
} | |
看正文 15 的代码,这里也是创立 ContextImpl 对象的实现,是创立 ContextImpl 子类具体对象呢?还是创立 ContextImpl 对象呢?咱们往下看 ContextImpl 的 createActivityContext 办法(参数太多我就不列举了,具体看上面代码);
static ContextImpl createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId, | |
Configuration overrideConfiguration) { | |
...... | |
//16、ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName, | |
activityToken, null, 0, classLoader); | |
...... | |
return context; | |
} | |
看正文 16 的代码,创立的是 ContextImpl 对象并返回,回到正文 6 的代码,所以 appContext 是 ContextImpl 对象,而不是 ContextImpl 子类具体对象;好,回到正文 8 处的代码,这里把 appContext 作为参数之一调用 Activity 的 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) { | |
//17、attachBaseContext(context); | |
...... | |
} | |
看正文 17 的代码,Activity 的 attach 办法又调用 ContextThemeWrapper 的 attachBaseContext(Context newBase) 办法(因为 Activity 继承于 ContextThemeWrapper);
@Override | |
protected void attachBaseContext(Context newBase) { | |
//18、super.attachBaseContext(newBase); | |
} | |
看正文 18 的代码,这里的 super 指的是 ContextWrapper,ContextThemeWrapper 的 attachBaseContext(Context newBase) 办法又调用了 ContextWrapper 的 attachBaseContext(Context base) 办法;
protected void attachBaseContext(Context base) {
if (mBase != null) {throw new IllegalStateException("Base context already set"); | |
} | |
mBase = base; | |
} | |
哈哈,看到了吧,正文 6 处的代码初始化的 ContextImpl 对象被赋值给了 Activity 的 mBase 变量,由此可见 Activity 的 mBase 变量实质上也是 ContextImpl 对象。
2、3 Service 的 mBase 变量是什么
其实 ApplicationThread 接管到创立 Service 的音讯跟 Activity 的是很相似的,这里就不再从 ApplicationThread 接管到创立 Service 的音讯入口进去剖析了,间接从创立 Service 的办法开始剖析,那就是 ActivityThread 的 handleCreateService(CreateServiceData data) 办法;
private void handleCreateService(CreateServiceData data) {
...... | |
Service service = null; | |
try {java.lang.ClassLoader cl = packageInfo.getClassLoader(); | |
//19、service = (Service) cl.loadClass(data.info.name).newInstance();} catch (Exception e) {if (!mInstrumentation.onException(service, e)) { | |
throw new RuntimeException( | |
"Unable to instantiate service" + data.info.name | |
+ ":" + e.toString(), e); | |
} | |
} | |
try {if (localLOGV) Slog.v(TAG, "Creating service" + data.info.name); | |
//20、ContextImpl context = ContextImpl.createAppContext(this, packageInfo); | |
context.setOuterContext(service); | |
Application app = packageInfo.makeApplication(false, mInstrumentation); | |
//21、service.attach(context, this, data.info.name, data.token, app, | |
ActivityManager.getService()); | |
service.onCreate(); | |
...... | |
} catch (Exception e) {......} | |
} | |
看正文 19 的代码,通反射机制创立一个 Service 对象;正文 20 的代码最终创立一个 ContextImpl 对象,具体实现和正文 9 的代码是一样的,后面曾经剖析了;看 21 正文的代码,把 ContextImpl 对象作为参数之一而后调用 Service 的 attach 办法(参数太多,列举不不便,具体看上面代码);
public final void attach(
Context context, | |
ActivityThread thread, String className, IBinder token, | |
Application application, Object activityManager) { | |
//22、attachBaseContext(context); | |
...... | |
} | |
看正文 22 的代码,Service 的 attach 办法调用了 ContextWrapper 的 attachBaseContext(Context base) 办法(因为 Service 继承于 ContextWrapper);
protected void attachBaseContext(Context base) {
if (mBase != null) {throw new IllegalStateException("Base context already set"); | |
} | |
mBase = base; | |
} | |
呼呼哈哈,又看到了吧,正文 20 处的代码初始化的 ContextImpl 对象被赋值给了 Service 的 mBase 变量,由此可见 Service 的 mBase 变量实质上又也是 ContextImpl 对象。
小结:哈哈,当初能够答复 Android 中 Application、Activity 和 Service 它们真正干活的 Context 是什么了,它不是 ContextWrapper,ContextWrapper 只是个代理,真正干活的是 ContextImpl。
本篇文章写到这里就完结了,因为技术水平无限,文章中难免会出错,欢送大家批评指正。