Android开发-Context理解(Applicatiion、Activity、Service 的Context区别)

Activity、Service、Application类继承关系

在这里插入图片描述

借助Context真正的实现类ContextImpl理解上面关系

Context 类提供了一组通用的 API;
ContextImpl 实现了 Context 所有的功能,为 Activity等应用组件提供 Context 对象;
ContextWrapper 包含一个真正的 ContextImpl 的引用 mBase,然后就是ContextImpl 的装饰者模式
ContextThemeWrapper 内部包含了 Theme 相关的接口,即android:theme 指定的属性;

Context 的数量及作用域

Context 数量 = Activity 数量 + Service 数量 + 1(Application 数量)

Context作用域ApplicationActivityService
Start an Activity不推荐YES不推荐
Show a DialogNOYESNO
Layout Inflation不推荐YES不推荐
Start a ServiceYESYESYES
Send a BroadcastYESYESYES
Register BroadcastYESYESYES
Load ResourceValuesYESYESYES

极大多数的场景Context对于各个组件是通用的,但是:

  • Dialog必须依附于Actiivity,否则会出错。
  • 启动的Activity是基于栈的,但是非Activity是没有栈的概念,所以需要指定FLAG_ACTIVITY_NEW_TASK,此时候Activity 是以SingleTask启动的,不推荐使用
  • Application 和 Service 中去 layout inflate 也是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用。所以这种方式也不推荐使用

获取Context对象

  • View 的 getContext 方法,返回 View 的 Context,通常是当前正在展示的 Activity 的对象,通常在自定义 View 时会用到;
  • Activity.this 返回当前 Activity 实例,如果是 UI 控件需要使用 Activity 作为 Context 对象,但是默认的 Toast 实际上使用 ApplicationContext 也可以;
  • Activity 和 Service 的getApplication 方法,返回 Application的实例;
  • getApplicationContext 方法,获取当前应用的 Context 对象,也就是Application对应的Context,与上一个方法不同的是依附的对象不同;

各个组件实例化Context的过程

Context 的实现是 ContextImpl,Activity、Application 和 Service 的创建都是在 ActivityThread 中完成的,分析ActivityThread中,实例并联系ContextImpl的过程。(activity启动过程中会调用到performLaunchActivity方法,具体的activity的启动过程课参考Activity的启动过程

Activity 中 ContextImpl实例过程

//创建Activity过程
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
****************
            if (activity != null) {
            //实例化ContextImpl过程
            Context appContext = createBaseContextForActivity(r, activity);
*******************************************
//attach方法,将context和组件Activity关联在一起
  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);

********************************************
      return activity;
    }

//createActivityContext就是一个静态方法,创建一个ContextImpl
private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
    *************************
        //创建ContextImpl
        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.token, displayId, r.overrideConfig);
        //核心方法:创建ContextImpl后,利用ContextImpl的setOuterContext(Context方法),
        //将ContextImpl的成员mOuterContext复值为Activity这个Context.也就是让ContextImpl内部持有Activity       
        appContext.setOuterContext(activity);
        //创建ContextImpl 直接赋值给你父类Context 
        Context baseContext = appContext;
    *************
        }
        return baseContext;
    }

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) {
      *************************************
        attachBaseContext(context);

      ************************************
        mCurrentConfig = config;
    }

@Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase);
    }

//父类 ContextWrapper.java中的attachBaseContext方法

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

Servicie中 ContextImpl实例过程

和Activity中实例Context过程一样的

private void handleCreateService(CreateServiceData data) {
       *************************************************
            //创建ContextImpl
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            //核心方法
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //将Context绑定Service
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());
            service.onCreate();
      ***************************************************
    }

上述创建Service过程中,ContextImpl.createAppContext 创建ContextImpl,然后绑定Context:service.attach

Application中 ContextImpl实例过程

  public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
  ****************************************************
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
   ********************************************************
        mActivityThread.mAllApplications.add(app);
        mApplication = app;

        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!instrumentation.onException(app, e)) {
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
        }
        return app;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值