android context继承关系,Android - 认识Context

app开发中,我们需要使用app的资源,比如文字、图片,Activity、Service或者broadcastReceiver等等。时常也会用到getApplicationContext()来获取一个Context对象。那么这个Context到底是什么呢?

我们一起来认识一下Android中的Context。本文主要内容如下图。

87031d6d7d05f39b22737fea9b7eb0eb.png

Context类简介

context含义有语境,上下文,背景,环境等等。

Context是维持Android程序中各组件能够正常工作的一个核心功能类。

Context是一个抽象类。它是一个 app 全局环境的“接口”,由 Android 系统提供继承类(例如Activity、Service、Application等)。它能连接到应用的资源,也能使用应用级的操作,比如启动activity,广播和接收intent。

应用程序中Context的总数目为:

总Context个数 = Activity个数 + Service个数 + 1(Application Context)

Context的子类

简单的继承关系示意

c2211b69d6fb936e02519277d573fd8a.png

Context

├── ContextImpl

└── ContextWrapper

├── Application

├── ContextThemeWrapper

│   └── Activity

└── Service

复制代码

从继承关系图中可以看出,Application类、Service类和Activity类都继承了Context类。应用程序被启动后,会为应用程序创建一个全局的Application对应的Context对象。ContextImpl类是Context的真正实现。ContextWrapper类是封装类。可以在不改变ContextImpl的情况下,为其增加一些自定义操作。ContextWrapper中的mBase实际上是一个ContextImpl对象。而ContextImpl类中的mOuterContext是一个Context对象,指向相对应的Activity或Service或Application。

ContextImpl

Context 是一个抽象类,子类 ContextImpl 实现了Context的方法;为Activity和其他应用组件提供基本的context对象。

ContextImpl.java (frameworks\base\core\java\android\app)

/**

* Common implementation of Context API, which provides the base

* context object for Activity and other application components.

*/

class ContextImpl extends Context{ /*...*/ }

复制代码

ContextWrapper

Wrapper 有封装的意思;ContextWrapper是Context的封装类 。这里使用了装饰者模式,构造方法中传入了一个Context 实例。ContextWrapper持有ContextImpl对象。可以在不改变ContextImpl的情况下增加一些操作。

ContextWrapper.java (frameworks\base\core\java\android\content)

/**

* Proxying implementation of Context that simply delegates all of its calls to

* another Context. Can be subclassed to modify behavior without changing

* the original Context.

*/

public class ContextWrapper extends Context{

Context mBase;

public ContextWrapper(Context base){

mBase = base;

}

// ...

}

复制代码

具体操作中,Application类、Activity和Service类与ContextImpl产生交集。

ContextThemeWrapper

允许在封装的context中修改主题(theme)

ContextThemeWrapper.java (frameworks\base\core\java\android\view)

/**

* A ContextWrapper that allows you to modify the theme from what is in the

* wrapped context.

*/

public class ContextThemeWrapper extends ContextWrapper{ /* ... */ }

复制代码

其中提供了关于theme的方法,app开发中 android:theme 与此有关。相同的代码,相同的调用,使用不同的 theme 会有不同的效果。

getApplicationContext() 和 getBaseContext()

public class ContextWrapper extends Context{

Context mBase;

......

@Override

public Context getApplicationContext(){

return mBase.getApplicationContext();

}

......

/**

* @return the base context as set by the constructor or setBaseContext

*/

public Context getBaseContext(){

return mBase;// Don't use getBaseContext(), just use the Context you have.

}

......

}

复制代码getApplicationContext() = android.app.Application@39d42b0e

getBaseContext() = android.app.ContextImpl@1f48c92f

复制代码

getApplicationContext() 从application取得context。getBaseContext() 从实现类ContextImpl那得来。

Context子类创建流程

Application的创建流程

我们把关注点先放在application上,暂时忽略源码中的其他信息。

a1dff77943050c8ea60ca844a6536bcc.png

流程描述:

LoadedApk先通过classLoader的loadClass(className)获取application的class,再通过clazz.newInstance()创建Application实例。接着调用app.attach(context)方法完成初始化。 Application的attach方法里调用了自己的attachBaseContext(context), 把第一步创建的ContextImpl实例赋值给ContextWrapper的mBase成员变量。 到此Application实例创建就完成了。

Activity的创建 - performLaunchActivity

这里关注的是Activity的实例化以及之前的一些准备过程。

6a3152c6f993a369bfcf060ca9266cc7.png

流程简析:

主要关注ActivityThread的performLaunchActivity方法。通过ContextImpl的createActivityContext获得一个ContextImpl实例,称为appContext。Instrumentation的newActivity返回了一个Activity实例。LoadedApk.makeApplication可以获得当前的application,如果当前没有则新建一个application。最后通过ContextImpl.setOuterContext和Activity的attach方法,将ContextImpl实例与Activity实例关联到一起。

使用

自定义Application

新建一个MyApplication类,继承自Application

import android.app.Application;

import android.content.Context;

public class MyApplication extends Application{

private static Context context;

public static Context getMyContext(){

return context;

}

@Override

public void onCreate(){

super.onCreate();

context = getApplicationContext();

}

}

复制代码

在Manifest中使用MyApplication;

android:name="com.rust.aboutview.MyApplication"

android:allowBackup="true"

android:icon="@mipmap/ic_launcher"

android:label="@string/app_name"

android:supportsRtl="true"

android:theme="@style/AppTheme">

......

复制代码

即可在不同的地方调用 getMyContext() 方法

MyApplication.getMyContext()

复制代码

参考

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值