Activity的Context介绍

Android  源码分析  2023年12月7日 pm12:12发布12个月前更新 城堡大人
141 0 0

前言

对于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-笔友城堡

 历史上的今天

  1. 2022: Android xml中selector配置选中按下等状态的透明度值(0条评论)
  2. 2021: Adapter的getView方法返回了null(0条评论)
  3. 2019: 茅盾:白杨礼赞(0条评论)
版权声明 1、 本站名称: 笔友城堡
2、 本站网址: https://www.biumall.com/
3、 本站部分文章来源于网络,仅供学习与参考,如有侵权,请留言

暂无评论

暂无评论...

随机推荐

bat脚本遍历

前言简单记录一下bat脚本(批处理文件)中的for循环命令。记录于此,方便自己查阅。正文遍历文件列表@echo off::遍历当前目录下扩展名为.php所有文件,并打印for %%i in (*.php) do ( echo %%i)遍历目录列表@echo of...

[转]Monkey测试基本命令

推荐使用 读书导航 极客导航 :125啦极客导航(http://www.biumall.com/jike.html)adb shell monkey -p com.xxxx.xxxx–pct-touch 30 –pct-motion 30 –pct-trackball 0 –pct-na...

纪伯伦:你的孩子其实不是你的孩子

你的孩子,其实不是你的孩子,他们是生命对于自身渴望而诞生的孩子。 他们通过你来到这世界,却非因你而来,他们在你身边,却并不属于你。 你可以给予他们的是你的爱,却不是你的想法,因为他们自己有自己的思想。 你可以庇护的是他们的身体,却不是他们的灵魂,...

梁实秋 :把快乐种在心里

天下最快乐的事大概莫过于做皇帝。“首出庶物,万国咸宁”。至不济可以生杀予夺,为所欲为。至于后宫粉黛三千,御膳八珍罗列,更是不在话下。清乾隆皇帝,“称八旬之觞,镌十全之宝”,三下江南,附庸风雅。那副志得意满的神情,真是不能不令人兴起“大丈夫当如是也”的感喟。在穷措大眼里,九五之尊,乐不可支。但是试...

Callable的简单使用

一、Callable的简介Callable是Java1.5中引入的一个接口,直接看官方文档:public interface Callable<V>A task that returns a result and may throw an exception. Impleme...

梁启超:为什么劝你在业余时间练书法

凡人必定要有娱乐。在正当的工作及研究学问以外,换一换空气找点娱乐品,精神才提得起来。假使全是义务工作,生活一定干燥、厌烦、无味。有一两样或者两三样娱乐品调剂一下,生活就有趣味多了。娱乐的工具很多,譬如喝酒、打牌、下棋、唱歌、听戏、弹琴、绘画、吟诗,都是娱乐,各有各的好处。但是要在各种娱乐之中,选择...