Activity的Context介绍

Android  源码分析  2023年12月7日 pm12:12发布11个月前更新 91es.com站长
120 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-91易搜》,知道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-91易搜

 历史上的今天

  1. 2022: Android xml中selector配置选中按下等状态的透明度值(0条评论)
  2. 2021: Adapter的getView方法返回了null(0条评论)
  3. 2019: 茅盾:白杨礼赞(0条评论)
版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站内容: 部分来源于网络,仅供学习和参考,若侵权请留言
3、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

activity-alias详解

activity-alias标签元素众所周知,AndroidManifest是一个xml文件,它包含很多标签元素,如application、activity、receiver等,其中有一个叫做activity-alias,因为该标签平时很少用到,可能大家对这个标签还不是很熟悉。activity...

OkHttp分析之异步请求

前言前面两篇文章介绍了OKHttp的《OkHttp简单介绍之一》和《OkHttp分析之同步请求》,大概的流程都介绍了,但上一篇只介绍了同步的,因此异步的也单独介绍一下,因为这个部分线程管理的思路很不错。正文OKHttp同步请求和异步请求唯一区别点是异步请求用了线程池管理,其的都是一样的,因此...

Android磁盘之U盘卸载

前言之前介绍了U盘的挂载,那当然不能少了U盘的卸载。这里大概的记录一下,方便自己查阅。Android P这里很多都是网上的,我就走走流程。正文VolumeManager.cpphandleBlockEvent()void VolumeManager::handleBlockEve...

JNI静态注册

前言之前其实写过,代码不见了,为了走一下流程,重新简单的写了一个。PS:设计NDK环境配置这里不介绍哈正文静态注册先由Java得到本地方法的声明,然后再通过JNI实现该声明方法。优点: 理解和使用方式简单, 属于傻瓜式操作, 使用相关工具按流程操作就行, 出错率低缺点: 当需...

Android 换肤setFactory2时出现No field mFactorySet in class问题解决

前言Android换肤插件开发时,需要依赖LayoutInflater.Factory类,在Android P和 之前版本都测试ok,但放在Android Q(10)上测试就失效了。本文记录一下失效的原因和解决的方法。正文在Android Q之前版本,通过如下代码可以设置的 try {...

[摘]Android中moveTo、lineTo、quadTo、cubicTo、arcTo详解

前言最近用Path的moveTo、lineTo、quadTo,也想整理一下,但看到网上已经有人整理了,就摘抄于此,方便自己查阅。好记性不如烂笔头正文一下内容摘抄的,原文请访问文末连接。moveTomoveTo 不会进行绘制,只用于移动移动画笔。就看做移动光标吧。lineTo画线...