Android中Application、Activity和Service它们真正干活的Context是什么?

文章收藏的好句子:真正的顺其自然,是竭尽所能后的不强求,而不是两手一摊的不作为。

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
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值