前言

对于Application,Activity和Service这几个类,我们是很[熟悉]的。确实[熟悉],作为App开发这基本都要面对这几个类。

比较好奇的朋友会发现,他们都拥有Context,但他们的Context有似乎有一点点的不同。今天有空,根据网上大佬的步伐,在这里简单记录一下。

正文

Context的使用场景

  1. 使用Context调用方法,比如启动Activity、访问资源、调用系统级服务等。

  2. 调用方法时传入Context,比如弹出Toast、创建Dialog等。

Context意为[上下文],也是Application,Activity和ServiceContext的祖先类。

Application -> ContextWrapper -> Context;
Activity -> ContextThemeWrapper -> ContextWrapper -> Context
Service -> ContextWrapper -> Context

或者看图,图上更详细

Activity的Context介绍

通过源码发现,Context其实也不干活的,具体干活的是ContextImpl。

今天介绍Activity的Context

Activity的Context

之前的源码分析startActivity源码分析2-笔友城堡》,知道ActivityThread.java中给Activity创建Context。

ActivityThread.java

大部分代码省略

handleLaunchActivity()
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
    //略
    final Activity a = performLaunchActivity(r, customIntent);
    //略
    return a;
}
performLaunchActivity()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //略
    //创建ContextImpl对象
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        //创建Activity对象,就是要启动的Activity
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        //略
    } catch (Exception e) {
        //略
    }
    try {
        //创建Application
        //makeApplication()中会判断mApplication是否为null,不为null直接返回mApplication
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        if (activity != null) {
            //略
            //把activity赋值给mOuterContext
            appContext.setOuterContext(activity);
            //activity绑定appContext
            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);
            //略
            //r.isPersistable()为false
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                //执行onCreate()流程
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            //略
            r.activity = activity;
        }
        r.setState(ON_CREATE);
        mActivities.put(r.token, r);
    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
        //略
    }
    return activity;
}

上面关注点

1. createBaseContextForActivity();
2. appContext.setOuterContext();
3. activity.attach();

下面进入简单介绍

createBaseContextForActivity()
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
    //略
    //ContextImpl的createActivityContext()进行创建
    ContextImpl appContext = ContextImpl.createActivityContext(
            this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
    //略
    return appContext;
}

最后调用ContextImpl()构造函数

ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
                activityToken, null, 0, classLoader);

ContextImpl.java

appContext.setOuterContext()

在ContextImpl.java中,这里是把activity赋值给mOuterContext

final void setOuterContext(Context context) {
    mOuterContext = context;
}

这里要知道的是mOuterContext是当前Activity实例,不过,这里并没有啥用处,可以略过。(仅记录一下)

Activity.java

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) {

    //[重]context绑定baseContext
    attachBaseContext(context);
    
    mFragments.attachHost(null /*parent*/);
    //创建Activity的PhoneWindow
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    mWindow.setWindowControllerCallback(this);
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);
    //略
}
attachBaseContext()
@Override
protected void attachBaseContext(Context newBase) {
	//调用父类的
    super.attachBaseContext(newBase);
    if (newBase != null) {
        newBase.setAutofillClient(this);
    }
}

ContextThemeWrapper.java

attachBaseContext()
@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(newBase);
}

ContextWrapper.java

attachBaseContext()
protected void attachBaseContext(Context base) {
	//mBase为null
    if (mBase != null) {
        throw new IllegalStateException("Base context already set");
    }
    mBase = base;
}

从这里看Activity和Application中的mBase不是一个变量,要不然mBase不为null了。如果不为null就会抛出异常!

参考文章

  1. Android进阶解密-刘望舒》

  2. 《Android内核剖析-柯元旦》

  3. startActivity源码分析2-笔友城堡

相关文章

暂无评论

none
暂无评论...