android 中application context 和 activity Context 阐释

前言

Context在开发Android应用的过程中扮演着非常重要的角色,

例如,启动一个 Activity需要使用context.startActivity方法,
将一个xml文件转换为一个View对象也需要使用Context对象,
弹窗需要context,资源获取需要,可以说没有Context,android开发
无从谈起

Applicaiton Context 和Activity Context 是否是同一个,能否混淆使用?

带着这个问题接着看;

类结构图
package android.content;

这里写图片描述

package android.app;

这里写图片描述

注意:
因为ContextImpl 和Context 不在同一个包下,用uml生成工具没能生成出来。下面的图是手动画的,应该合起来看。


Context本身是一个纯的abstract类。

ContextWrapper是对Context的一个包装而已,它的内部包含了一个 Context对象,其实对ContextWrapper的方法调用最终都是调用其中的Context对象完成的,

ContextThremeWrapper,很明显和Theme有关,所以Activity从ContextThemmWrapper继承,而 Service,application 没有主题 所从ContextWrapper继承,

ContextImpl是唯一 一个真正实现了Context中方法的类。

从上面的继承关系来看,每一个Activity就是一个Context,每一个Service就是一个Context,每一个Application就是一个Context,这也就是为什么使用Context的地方可以被Activity,Service或者Application替换了。

根据上面所介绍的,实现Context的只有Contextimpl类,其它是对context的包装,最终调用的还是的Contextimpl类,所以Activity,application,service 创建的时候肯定要创建一个ContextImpl对象,赋值给 Activity,application,service 中的context。口说无凭,跟着源码来看。

步骤一

分析startActivity()流程的,最后进入T和threadActivity中的 performLaunchActivity()方法

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

   if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
.....
.....
}

}

进入 createBaseContextForActivity()方法

 private Context createBaseContextForActivity(ActivityClientRecord r,
            final Activity activity) {
        ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
        appContext.setOuterContext(activity);
        Context baseContext = appContext;

        final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
        try {
            IActivityContainer container =
                    ActivityManagerNative.getDefault().getEnclosingActivityContainer(r.token);
            final int displayId =
                    container == null ? Display.DEFAULT_DISPLAY : container.getDisplayId();
            if (displayId > Display.DEFAULT_DISPLAY) {
                Display display = dm.getRealDisplay(displayId, r.token);
                baseContext = appContext.createDisplayContext(display);
            }
        } catch (RemoteException e) {
        }

        // For debugging purposes, if the activity's package name contains the value of
        // the "debug.use-second-display" system property as a substring, then show
        // its content on a secondary display if there is one.
        String pkgName = SystemProperties.get("debug.second-display.pkg");
        if (pkgName != null && !pkgName.isEmpty()
                && r.packageInfo.mPackageName.contains(pkgName)) {
            for (int displayId : dm.getDisplayIds()) {
                if (displayId != Display.DEFAULT_DISPLAY) {
                    Display display = dm.getRealDisplay(displayId, r.token);
                    baseContext = appContext.createDisplayContext(display);
                    break;
                }
            }
        }
        return baseContext;
    }

这里这是证明 activity 创建过程中会初始化 contextImpl 实现类,关于Application,service 自行查看源码,这里不过多解释。

建议直接查看 contextImpl 类,该类里面罗列了所有初始化方法。

这里写图片描述

到这里共说明了

1.application,service,activity与Context的关系。
2.application 和 activity之间是否可以替换,为什么不可以替换
3.context的类继承树

在此总结一下:

(1)Context是一个抽象类,ContextWrapper是对Context的封装,它包含一个Context类型的变 量,ContextWrapper的功能函数内部其实都是调用里面的Context类型变量完成的。 Application,Service,Activity等都是直接或者间接继承自ContextWrapper,但是并没有真正的实现其中的功 能,Application,Service,Activity中关于Context的功能都是通过其内部的Context类型变量完成的,而这个变量的 真实对象必定是ContextImpl,所以没创建一个Application,Activity,Servcice便会创建一个 ContextImpl,并且这些ContextImpl中的mPackages和mResources变量都是一样的,所以不管使用Acitivty还 是Service调用getResources得到相同的结果

(2)在一个apk中,Context的数量等于Activity个数+Service个数+application个数.

关于上面提出来问题,为什么不可以互换,很简单解释 Application 和Activity的上下文Context 不是同一个,继承树不同。Application 继承自contextWrapper,而Activity继承自ThemeWarpper. 还有Dialog弹窗和当前Activity绑定,自然不能使用Application的Context进行传值。

引用

context 解释 http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1223/2205.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灯塔@kuaidao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值