关于android:Android中ApplicationActivity和Service它们真正干活的Context是什么

6次阅读

共计 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。

本篇文章写到这里就完结了,因为技术水平无限,文章中难免会出错,欢送大家批评指正。

正文完
 0