Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 861|回复: 0

[默认分类] Context对象创建详解

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-7-1 10:25:16 | 显示全部楼层 |阅读模式

    Context是什么
    context在日常的开发中经常被用到,扮演着一个很重要的角色,因为Context会返回一些全局对象(例如Resources类等)让我们获取一些信息,context被叫做作“上下文“。
    Context的作用

      启动Activity
      启动和停止Service
      发送广播消息(Intent)
      注册广播消息(Intent)接收者
      可以访问APK中各种资源(如Resources)
      可以访问Package的相关信息
      APK的各种权限管理等等等等。

    Context的继承关系

    Context的一个抽象类。
    定义了ContextWrapper类继承与Context。从名字看这个是一个包装类。
    定义了ContextThemeWrapper类继承于Context Wrapper,该内部包含了主题相关的接口,可以在清单文件的android:theme属性指定主题。
    只有Activity需要主题,因为Service是执行后台的计算没有界面不需要主题,因此直接继承于ContextWrapper。
    ContextImpl类真正的实现Context中的所有函数,应用程序调用Context的方法的实现细节都在ContextImpl类中。
    从继承图可以看到,Activity和Service也是Context 。
    其实Application也是继承与ContextWrapper类:
    1. [code]public class Application extends ContextWrapper implements ComponentCallbacks2 {......}
    复制代码
    [/code]
    因此一个应用程序包含的Context的数量有:
    App 的Context数量 = Application对象(1个) + Activity数量 + Service数量
    Context创建的时机
    我们只看Activity的Context对象的创建的时机。
    在分析Activity的运行过程文章中,在performLaunchActivity()方法中做了几个重要的操作,其中一个就是创建ContextImpl对象。进入performLaunchActivity()方法:
    1. [code]private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    2.         ......
    3.         Activity activity = null;
    4.        ......
    5.             java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    6.             activity = mInstrumentation.newActivity(
    7.                     cl, component.getClassName(), r.intent);
    8. .....
    9.             Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    10. ......
    11.                 Context appContext = createBaseContextForActivity(r, activity);
    12. ......
    13.                 activity.attach(appContext, this, getInstrumentation(), r.token,
    14.                         r.ident, app, r.intent, r.activityInfo, title, r.parent,
    15.                         r.embeddedID, r.lastNonConfigurationInstances, config,
    16.                         r.referrer, r.voiceInteractor);
    17. ......
    18.   if (r.isPersistable()) {
    19.                     mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    20.                 } else {
    21.                     mInstrumentation.callActivityOnCreate(activity, r.state);
    22.                 }
    23.        ......
    24.         return activity;
    25.     }
    复制代码
    [/code]
    从代码中看到,调用了createBaseContextForActivity(r, activity);方法创建了Context对象。进入该方法:
    1. [code]
    2.     private Context createBaseContextForActivity(ActivityClientRecord r,
    3.                                                  final Activity activity) {
    4.         ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
    5.         appContext.setOuterContext(activity);
    6.         Context baseContext = appContext;
    7.         final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
    8.         try {
    9.             final int displayId = ActivityManagerNative.getDefault().getActivityDisplayId(r.token);
    10.             if (displayId > Display.DEFAULT_DISPLAY) {
    11.                 Display display = dm.getRealDisplay(displayId, r.token);
    12.                 baseContext = appContext.createDisplayContext(display);
    13.             }
    14.         } catch (RemoteException e) {
    15.         }
    16.         // For debugging purposes, if the activity"s package name contains the value of
    17.         // the "debug.use-second-display" system property as a substring, then show
    18.         // its content on a secondary display if there is one.
    19.         String pkgName = SystemProperties.get("debug.second-display.pkg");
    20.         if (pkgName != null && !pkgName.isEmpty()
    21.                 && r.packageInfo.mPackageName.contains(pkgName)) {
    22.             for (int displayId : dm.getDisplayIds()) {
    23.                 if (displayId != Display.DEFAULT_DISPLAY) {
    24.                     Display display = dm.getRealDisplay(displayId, r.token);
    25.                     baseContext = appContext.createDisplayContext(display);
    26.                     break;
    27.                 }
    28.             }
    29.         }
    30.         return baseContext;
    31.     }
    复制代码
    [/code]
    在这个方法中,两个重要的操作:
    创建ContextImpl对象
    1. [code]   static ContextImpl createActivityContext(ActivityThread mainThread,
    2.                                              LoadedApk packageInfo, IBinder activityToken) {
    3.         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
    4.         if (activityToken == null) throw new IllegalArgumentException("activityInfo");
    5.         return new ContextImpl(null, mainThread,
    6.                 packageInfo, activityToken, null, false, null, null);
    7.     }
    复制代码
    [/code]
    很简单,其实就是new 了一个ContextImpl对象。
    在ContextImpl内部保存Activity对象。
    1. [code]    private Context mOuterContext;
    2.    final void setOuterContext(Context context) {
    3.         mOuterContext = context;
    4.     }
    复制代码
    [/code]
    从上述代码中可以看到Activity对象保存在mOuterContext成员变量中,以便操作Activity组件。
    当Context对象创建出来了,Activity应该把这个对象保存起来才对。而这个保存的操作在Activity的attch方法中保存了,进入该方法看看:
    1. [code]final void attach(Context context, ActivityThread aThread,
    2.             Instrumentation instr, IBinder token, int ident,
    3.             Application application, Intent intent, ActivityInfo info,
    4.             CharSequence title, Activity parent, String id,
    5.             NonConfigurationInstances lastNonConfigurationInstances,
    6.             Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
    7.         attachBaseContext(context);
    8.         ...
    9.         ...
    复制代码
    [/code]
    调用了attacHbaseContext方法,这个是父类ContextThemeWrapper的方法。
    1. [code] @Override
    2.     protected void attachBaseContext(Context newBase) {
    3.         super.attachBaseContext(newBase);
    4.     }
    复制代码
    [/code]
    又调用了父类ContextWrapper的attachBaseContext方法:
    1. [code]  protected void attachBaseContext(Context base) {
    2.         if (mBase != null) {
    3.             throw new IllegalStateException("Base context already set");
    4.         }
    5.         mBase = base;
    6.     }
    复制代码
    [/code]
    其实就是把创建出来的Context对象保存在mBase成员变量中。Activity可以通过ContextImpl对象获取Resouces,发送广播,启动Service等功能了。
    可以看出每一Activity都会关联一个Context。
    END。

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-17 00:05 , Processed in 0.424515 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表