关于Context和ContextImpl还有ContextWrapper的关系

news2024/9/24 11:27:29

关于Context和ContextImpl还有ContextWrapper的关系

1.Context和ContextImpl还有ContextWrapper的关系

img

​ 图一.Context和ContextImpl还有ContextWrapper的关系示意图

1.1.ContextImpl是Context的实现类

从Context和ContextImpl的源代码中,可以看出Context是一个抽象类,具体的实现类是ContextImpl

public abstract class Context {

Context.java文件

class ContextImpl extends Context {....}

ContextImpl.java文件

1.2.ContextWrapper是Context的包装类

从ContextWrapper的源代码可以看出,ContextWrapper继承自Context; 并且ContextWrapper类持有Context的引用;

所以最终是要通过java的多态这个属性,调用Context类的相关方法,实际上是调用ContextImpl类里面的方法

public class ContextWrapper extends Context {
    @UnsupportedAppUsage
    Context mBase;

ContextWrapper.java文件

2.ContextImpl跟ContextWrapper的关联过程

2.1.ContextWrapper可以关联的可能入口

根据下面的ContextWrapper的源码的解读,如果ContextWrapper关联ContextImpl,

只有两个地方可以把Context作为参数传进来

第一个:ContextWrapper的构造函数

第二个:attachBaseContext函数

这两个函数都会把context 赋值给名字为mBase的Context的属性

public class ContextWrapper extends Context {
    @UnsupportedAppUsage
    Context mBase;

    @GuardedBy("mLock")
    @VisibleForTesting
    public List<ComponentCallbacks> mCallbacksRegisteredToSuper;

    private final Object mLock = new Object();

    public ContextWrapper(Context base) {
        mBase = base;
    }

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

2.2.Context创建过程

public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        
             //TODO 
             ......
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            // The network security config needs to be aware of multiple
            // applications in the same process to handle discrepancies
            NetworkSecurityConfigProvider.handleNewApplication(appContext);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + " package " + mPackageName + ": " + e.toString(), e);
            }
        }
        //TODO 
        ......

        return app;
    }

LoadedApk.java

在LoadedApk的函数makeApplication中,下面这段语句通过调用了ContextImpl.createAppContext 生成了ContextImpl对象

ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);

在ContextImpl类中,createAppContext函数,调用了另外一个带3个参数的重写函数createAppContext,

可以看出在这个函数里面,通过ContextImpl context = new ContextImpl 这个语句 创建了ContextImpl类的对象,

然后通过函数返回,返回了这个ContextImpl类的对象.

@UnsupportedAppUsage
    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        return createAppContext(mainThread, packageInfo, null);
    }

    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
            String opPackageName) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo,
            ContextParams.EMPTY, null, null, null, null, null, 0, null, opPackageName);
        context.setResources(packageInfo.getResources());
        context.mContextType = isSystemOrSystemUI(context) ? CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI
                : CONTEXT_TYPE_NON_UI;
        return context;
    }

上面的步骤创建了appContext,然后通过下面的函数调用把对象appContext传递下去

app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);

在Instrumentation源代码中,newApplication 函数中,Application的attach函数,通过此函数, 把context传递下去

    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }

Instrumentation.java

Application类的attach函数,在这个函数中,会把传递进来的context 传递给attachBaseContext函数, attachBaseContext 函数是父类ContextWrapper的函数

同时验证了上面的结论(2.1.ContextWrapper可以关联的可能入口)

public class Application extends ContextWrapper implements ComponentCallbacks2 {
    @UnsupportedAppUsage
    /* package */ final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }

Application.java

在ContextWrapper的源代码中,可以看到context会在attachBaseContext中赋值给名字为mBase的Context对象的属性

public class ContextWrapper extends Context {
    @UnsupportedAppUsage
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }

    /**
     * Set the base context for this ContextWrapper.  All calls will then be
     * delegated to the base context.  Throws
     * IllegalStateException if a base context has already been set.
     *
     * @param base The new base context for this wrapper.
     */
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

ContextWrapper.java

到此处为止,ContextImpl 跟ContextWrapper 的关联已经完成

引用:
Android 开发者,你真的懂Context吗?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/758423.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pytorch+CRNN实现

最近接触了一个仪表盘识别的项目&#xff0c;简单调研以后发现可以用CRNN来做。但是手边缺少仪表盘数据集&#xff0c;就先用ICDAR2013试了一下。 结果遇到了一系列坑。为了不使读者和自己在以后的日子继续遭罪。我把正确的代码发到下面了。 1&#xff09;超参数请不要调整&am…

实体店搭建多用户商城系统有什么好处

现在很多的线下店铺都开始慢慢的转型线上了&#xff0c;想线上线下相结合&#xff0c;但是最近很多的商家都在问什么样的B2B2C商城系统开发适合线下店铺呢?这个问题今天加速度jsudo小编给大家一起整理如下&#xff0c;相信商家看完后就知道如何选择一款合适的商城系统了。 一、…

Spring Batch之读数据—读XML文件(三十二)

一、XML格式文件解析 XML是一种通用的数据交换格式&#xff0c;它的平台无关性、语言无关性、系统无关性&#xff0c;给数据集成与交换带来了极大的方便。XML在Java领域的解析方式有两种&#xff0c;一种叫SAX&#xff0c;另一种叫DOM。SAX是基于事件流的解析&#xff0c;DOM是…

刷题总结1

暑假第二周练习题 - Virtual Judge (vjudge.net) 该题就是将含4的数字全部跳过&#xff0c;不难发现&#xff0c;这就导致每位数都要少一个树&#xff0c;这就和9进制十分像&#xff0c;我们只要将该数字转化为9进制&#xff0c;然后将该9进制树的每位大于等于4的树加一就行了&…

【CXL】CXL QoS Telemetry 介绍

&#x1f525;点击查看精选 CXL 系列文章&#x1f525; &#x1f525;点击进入【芯片设计验证】社区&#xff0c;查看更多精彩内容&#x1f525; &#x1f4e2; 声明&#xff1a; &#x1f96d; 作者主页&#xff1a;【MangoPapa的CSDN主页】。⚠️ 本文首发于CSDN&#xff0c…

51单片机的智能交通控制系统【含仿真+程序+演示视频带原理讲解】

51单片机的智能交通控制系统【含仿真程序演示视频带原理讲解】 1、系统概述2、核心功能3、仿真运行及功能演示4、程序代码 1、系统概述 该系统由AT89C51单片机、LED灯组、数码管组成。通过Protues对十字路口红绿灯控制逻辑进行了仿真。 每个路口包含了左转、右转、直行三条车道…

rapid_latex_ocr: 更快更好用的公式图像转latex工具

Rapid Latex OCR rapid_latex_ocr是一个将公式图像转为latex格式的工具。仓库中的推理代码来自修改自LaTeX-OCR&#xff0c;模型已经全部转为ONNX格式&#xff0c;并对推理代码做了精简&#xff0c;推理速度更快&#xff0c;更容易部署。仓库只有基于ONNXRuntime或者OpenVINO推…

AI辅助瞄准系统开发与实战(一)

文章目录 前言系统窗体设计提示弹窗功能主体页面 windows窗体绘制矩形绘制自定义线程池完整代码 总结 前言 直接看效果&#xff0c;狗头&#xff1a; 之所以搞这个的话&#xff0c;当然主要一方面是因为确实有点意思在里面&#xff0c;此外在很久以前&#xff0c;也有很多的UP…

光伏并网逆变器低电压穿越MATLAB仿真模型

使用MATLAB 2017b搭建 光伏逆变器低电压穿越仿真模型&#xff0c;boost加NPC拓扑结构&#xff0c;基于MATLAB/Simulink建模仿真。具备中点平衡SVPWM控制&#xff0c;正负序分离控制&#xff0c;pll&#xff0c;可进行低电压穿越仿真。 控制结构完整&#xff0c;波形完美&…

Web入门-HTTP协议

目录 HTTP概述 HTTP特点 HTTP请求协议 请求数据的格式 响应数据的格式 响应的状态码 HTTP协议的解析 HTTP概述 HTTP:Hyper Text Transfer Protocol&#xff0c;超文本传输协议&#xff0c;规定浏览器和服务器之间数据传输的规则。(即请求数据和响应数据的格式)以上一篇…

动态规划之119杨辉三角 II(第7道)

题目&#xff1a;给定一个非负索引 rowIndex&#xff0c;返回「杨辉三角」的第 rowIndex 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 题目链接&#xff1a;119. 杨辉三角 II - 力扣&#xff08;LeetCode&#xff09; 示例&#xff1a; 解法&…

高阶C语言|字符函数和字符串函数--函数的模拟实现

C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在常量字符串中或者字符数组中。字符串常量适用于那些对它不做修改的字符串函数 字符函数和字符串函数 一、求字符串长度1.1strlen的使用1.2strlen函数的模拟实现 二…

基于linux下的高并发服务器开发(第一章)- 模拟实现 ls-l 命令

这一小节会用到上面两张图的红色框里面的变量 任务&#xff1a; 模拟实现 ls -l 指令 -rw-rw-r-- 1 nowcoder nowcoder 12 12月 3 15:48 a.txt #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <p…

C++中菱形继承中继承不明确问题

C中菱形继承中继承不明确问题 class A { public:virtual void func1(){cout << "A::func1()" << endl;}int _a; };class B:virtual public A { public:virtual void func1(){cout << "B::func1()" << endl;}int _b; };class C:vi…

JavaScript混淆加密:Ty2y平台配置参数详解

Ty2y是国内一个JavaScript混淆加密平台&#xff0c;可以实现在线JS代码混淆加密。它有多达20多项的参数配置。如下图所示&#xff1a; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 本文将对这些配置实现的混淆加密的效果&#xff0c;进行详细说明&…

基于自注意和残差结构的跨模态情感识别融合网络

题目A cross-modal fusion network based on self-attention and residual structure for multimodal emotion recognition译题基于自注意和残差结构的跨模态情感识别融合网络时间2021年代码https://github.com/skeletonNN/CFN-SR A cross-modal fusion network based on self…

verilog实现数码管静态显示

文章目录 verilog实现数码管静态显示一、任务要求二、实验代码三、仿真代码四、仿真结果五、总结 verilog实现数码管静态显示 一、任务要求 六个数码管同时间隔0.5s显示0-f。要求&#xff1a;使用一个顶层模块&#xff0c;调用计时器模块和数码管静态显示模块。 二、实验代码…

DS-SLAM论文翻译

DS-SLAM:面向动态环境的语义可视化SLAM 摘要-同时定位与绘图(SLAM)被认为是智能移动机器人的一项基本能力。在过去的几十年里&#xff0c;许多印象深刻的SLAM系统已经开发出来&#xff0c;并在某些情况下取得了良好的性能。然而&#xff0c;一些问题仍然没有很好地解决&#x…

windows下mingw 编译boost-1.78.0

1.mingw环境设置 添加C:\cygwin64\bin 到环境变量&#xff0c;cmd运行检查是否安装成功 打开cmd&#xff0c;验证&#xff1a; 2.boost编译 创建文件夹 #后期可以删除&#xff0c;安装Boost.Buildmkdir D:\boost_build#后期可以删除&#xff0c;存放mkdir D:\boost_1_78_0\b…

SpringBoot使用Redis作为缓存器缓存数据的操作步骤以及避坑方案

1.非注解式实现 2.1使用之前要明确使用的业务场景 例如我们在登录时&#xff0c;可以让redis缓存验证码&#xff0c;又如在分类下显示菜品数据时&#xff0c;我们可以对分类和菜品进行缓存数据等等。 2.2导入Redis相关依赖 <dependency><groupId>org.springfra…