ContextImpl关键成员和函数

/**

* Common implementation of Context API, which provides the base

* context object for Activity and other application components.

*/

classContextImplextendsContext {

privatefinalstaticString TAG ="ContextImpl";

privatefinalstaticbooleanDEBUG =false;

privatestaticfinalHashMap sSharedPrefs =

newHashMap();

/*package*/LoadedApk mPackageInfo;// 关键数据成员

privateString mBasePackageName;

privateResources mResources;

/*package*/ActivityThread mMainThread;// 主线程

@Override

publicAssetManager getAssets() {

returngetResources().getAssets();

}

@Override

publicLooper getMainLooper() {

returnmMainThread.getLooper();

}

@Override

publicObject getSystemService(String name) {

ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);

returnfetcher ==null?null: fetcher.getService(this);

}

@Override

publicvoidstartActivity(Intent intent, Bundle options) {

warnIfCallingFromSystemProcess();

if((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) ==0) {

thrownewAndroidRuntimeException(

"Calling startActivity() from outside of an Activity "

+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."

+ " Is this really what you want?");

}

mMainThread.getInstrumentation().execStartActivity(

getOuterContext(), mMainThread.getApplicationThread(), null,

(Activity)null, intent, -1, options);

}

}

ContextWrapper

它只是对Context类的一种封装,它的构造函数包含了一个真正的Context引用,即ContextImpl对象。

/**

* 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.

*/

publicclassContextWrapperextendsContext {

Context mBase; //该属性指向一个ContextIml实例

publicContextWrapper(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.

* 创建Application、Service、Activity,会调用该方法给mBase属性赋值

*/

protectedvoidattachBaseContext(Context base) {

if(mBase !=null) {

thrownewIllegalStateException("Base context already set");

}

mBase = base;

}

@Override

publicLooper getMainLooper() {

returnmBase.getMainLooper();

}

@Override

publicObject getSystemService(String name) {

returnmBase.getSystemService(name);

}

@Override

publicvoidstartActivity(Intent intent) {

mBase.startActivity(intent);

}

}

ContextThemeWrapper

该类内部包含了主题(Theme)相关的接口,即android:theme属性指定的。只有Activity需要主题,Service不需要主题,所以Service直接继承于ContextWrapper类。

/**

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

* wrapped context.

*/

publicclassContextThemeWrapperextendsContextWrapper {

privateContext mBase;

privateintmThemeResource;

privateResources.Theme mTheme;

privateLayoutInflater mInflater;

privateConfiguration mOverrideConfiguration;

privateResources mResources;

publicContextThemeWrapper() {

super(null);

}

publicContextThemeWrapper(Context base,intthemeres) {

super(base);

mBase = base;

mThemeResource = themeres;

}

@OverrideprotectedvoidattachBaseContext(Context newBase) {

super.attachBaseContext(newBase);

mBase = newBase;

}

@OverridepublicvoidsetTheme(intresid) {

mThemeResource = resid;

initializeTheme();

}

@OverridepublicResources.Theme getTheme() {

if(mTheme !=null) {

returnmTheme;

}

mThemeResource = Resources.selectDefaultTheme(mThemeResource,

getApplicationInfo().targetSdkVersion);

initializeTheme();

returnmTheme;

}

}

何时创建Context

应用程序在以下几种情况下创建Context实例:

1) 创建Application 对象时, 而且整个App共一个Application对象

2) 创建Service对象时

3) 创建Activity对象时

因此应用程序App共有的Context数目公式为:

总Context实例个数 = Service个数 + Activity个数 + 1(Application对应的Context实例)

ActivityThread消息处理函数与本节相关的内容如下:

publicvoidhandleMessage(Message msg) {

if(DEBUG_MESSAGES) Slog.v(TAG,">>> handling: "+ codeToString(msg.what));

switch(msg.what) {

caseLAUNCH_ACTIVITY: {// 创建Activity对象

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");

ActivityClientRecord r = (ActivityClientRecord)msg.obj;

r.packageInfo = getPackageInfoNoCheck(

r.activityInfo.applicationInfo, r.compatInfo);

handleLaunchActivity(r, null);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

} break;

caseBIND_APPLICATION:// 创建Application对象

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");

AppBindData data = (AppBindData)msg.obj;

handleBindApplication(data);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

break;

caseCREATE_SERVICE:// 创建Service对象

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");

handleCreateService((CreateServiceData)msg.obj);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

break;

caseBIND_SERVICE:// Bind Service对象

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");

handleBindService((BindServiceData)msg.obj);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

break;

}

}

创建Application对象时创建Context实例

每个应用程序在第一次启动时,都会首先创建一个Application对象。从startActivity流程可知,创建Application的时机在handleBindApplication()方法中,该函数位于 ActivityThread.java类中 ,相关代码如下:

// ActivityThread.java

privatevoidhandleBindApplication(AppBindData data) {

try{

// If the app is being launched for full backup or restore, bring it up in

// a restricted environment with the base application class.

Application app = data.info.makeApplication(data.restrictedBackupMode, null);

mInitialApplication = app;

...

} finally{

StrictMode.setThreadPolicy(savedPolicy);

}

}

// LoadedApk.java

publicApplication makeApplication(booleanforceDefaultAppClass,

Instrumentation instrumentation) {

if(mApplication !=null) {

returnmApplication;

}

Application app = null;

String appClass = mApplicationInfo.className;

if(forceDefaultAppClass || (appClass ==null)) {

appClass = "android.app.Application";

}

try{

java.lang.ClassLoader cl = getClassLoader();

ContextImpl appContext = newContextImpl();// 创建ContextImpl实例

appContext.init(this,null, mActivityThread);

app = mActivityThread.mInstrumentation.newApplication(

cl, appClass, appContext);

appContext.setOuterContext(app); // 将Application实例传递给Context实例

} catch(Exception e) {

...

}

mActivityThread.mAllApplications.add(app);

mApplication = app;

returnapp;

}

创建Activity对象时创建Context实例

通过startActivity()或startActivityForResult()请求启动一个Activity时,如果系统检测需要新建一个Activity对象时,就会回调handleLaunchActivity()方法,该方法继而调用performLaunchActivity()方法,去创建一个Activity实例,并且回调onCreate(),onStart()方法等,函数都位于 ActivityThread.java类 ,相关代码如下:

privatevoidhandleLaunchActivity(ActivityClientRecord r, Intent customIntent) {

...

Activity a = performLaunchActivity(r, customIntent); // 到下一步

if(a !=null) {

r.createdConfig = newConfiguration(mConfiguration);

Bundle oldState = r.state;

handleResumeActivity(r.token, false, r.isForward,

!r.activity.mFinished && !r.startsNotResumed);

...

}

...

}

privateActivity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

...

Activity activity = null;

try{

java.lang.ClassLoader cl = r.packageInfo.getClassLoader();

activity = mInstrumentation.newActivity(

cl, component.getClassName(), r.intent);

StrictMode.incrementExpectedActivityCount(activity.getClass());

r.intent.setExtrasClassLoader(cl);

if(r.state !=null) {

r.state.setClassLoader(cl);

}

} catch(Exception e) {

...

}

try{

Application app = r.packageInfo.makeApplication(false, mInstrumentation);

if(activity !=null) {

Context appContext = createBaseContextForActivity(r, activity); // 创建Context

CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());

Configuration config = newConfiguration(mCompatConfiguration);

if(DEBUG_CONFIGURATION) Slog.v(TAG,"Launching activity "

+ r.activityInfo.name + " with config "+ config);

activity.attach(appContext, this, getInstrumentation(), r.token,

r.ident, app, r.intent, r.activityInfo, title, r.parent,

r.embeddedID, r.lastNonConfigurationInstances, config);

if(customIntent !=null) {

activity.mIntent = customIntent;

}

r.lastNonConfigurationInstances = null;

activity.mStartedActivity = false;

inttheme = r.activityInfo.getThemeResource();

if(theme !=0) {

activity.setTheme(theme);

}

mActivities.put(r.token, r);

} catch(SuperNotCalledException e) {

...

} catch(Exception e) {

...

}

returnactivity;

}

privateContext createBaseContextForActivity(ActivityClientRecord r,

finalActivity activity) {

ContextImpl appContext = newContextImpl();// 创建ContextImpl实例

appContext.init(r.packageInfo, r.token, this);

appContext.setOuterContext(activity);

// 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.

Context baseContext = appContext;

String pkgName = SystemProperties.get("debug.second-display.pkg");

if(pkgName !=null&& !pkgName.isEmpty()

&& r.packageInfo.mPackageName.contains(pkgName)) {

DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();

for(intdisplayId : dm.getDisplayIds()) {

if(displayId != Display.DEFAULT_DISPLAY) {

Display display = dm.getRealDisplay(displayId);

baseContext = appContext.createDisplayContext(display);

break;

}

}

}

returnbaseContext;

}

创建Service对象时创建Context实例

通过startService或者bindService时,如果系统检测到需要新创建一个Service实例,就会回调handleCreateService()方法,完成相关数据操作。handleCreateService()函数位于 ActivityThread.java类,如下:

privatevoidhandleCreateService(CreateServiceData data) {

// If we are getting ready to gc after going to the background, well

// we are back active so skip it.

unscheduleGcIdler();

LoadedApk packageInfo = getPackageInfoNoCheck(

data.info.applicationInfo, data.compatInfo);

Service service = null;

try{

java.lang.ClassLoader cl = packageInfo.getClassLoader();

service = (Service) cl.loadClass(data.info.name).newInstance();

} catch(Exception e) {

if(!mInstrumentation.onException(service, e)) {

thrownewRuntimeException(

"Unable to instantiate service "+ data.info.name

+ ": "+ e.toString(), e);

}

}

try{

if(localLOGV) Slog.v(TAG,"Creating service "+ data.info.name);

ContextImpl context = newContextImpl();// 创建ContextImpl实例

context.init(packageInfo, null,this);

Application app = packageInfo.makeApplication(false, mInstrumentation);

context.setOuterContext(service);

service.attach(context, this, data.info.name, data.token, app,

ActivityManagerNative.getDefault());

service.onCreate();

mServices.put(data.token, service);

try{

ActivityManagerNative.getDefault().serviceDoneExecuting(

data.token, 0,0,0);

} catch(RemoteException e) {

// nothing to do.

}

} catch(Exception e) {

if(!mInstrumentation.onException(service, e)) {

thrownewRuntimeException(

"Unable to create service "+ data.info.name

+ ": "+ e.toString(), e);

}

}

}

小结

通过对ContextImp的分析可知,其方法的大多数操作都是直接调用其属性mPackageInfo(该属性类型为PackageInfo)的相关方法而来。这说明ContextImp是一种轻量级类,而PackageInfo才是真正重量级的类。而一个App里的所有ContextImpl实例,都对应同一个packageInfo对象。

【责任编辑:chenqingxiang TEL:(010)68476606】

android tag的作用,Android中的Context的作用(2)相关推荐

  1. android tag定义快捷键,Android Studio快捷键生成TAG、Log.x日志输出介绍

    生成TAG logt+Tab键: private static final String TAG = "Extract"; 生成Log.d() logd+Tab键: Log.d(T ...

  2. 查看mysql view作用_Mysql中View视图的作用

    浙江PHP博客分享关于Mysql中使用View视图的作用.很多小伙伴知道视图的作用,却不知道为什么要使用视图以及视图的一些好处是什么,下面浙江一点PHP将详细阐述关于视图的用法以及作用. 作用一: 提 ...

  3. 在html中base的作用,html中base标签的作用是什么

    html中base标签的作用是什么? 作用:为页面上的所有链接规定默认地址或默认目标,是一种表达路径和连接网址的标签. 说明:通常情况下,浏览器会从当前文档的 URL 中提取相应的元素来填写相对 UR ...

  4. 计算机技术在多媒体教学中的作用,多媒体教学中的现状及作用

    多媒体教学中的现状及作用 1 计算机多媒体教学现状 我国的教育正在逐步向现代教育迈进,摆脱传统的教师-黑板-学生模式.自素质教育提出,我国就充分地意识到发挥学生的主动性.积极性.创造性的重要作用,重在 ...

  5. python装饰器作用-python中装饰器的作用

    装饰器的作用就是用一个新函数封装旧函数(是旧函数代码不变的情况下增加功能)然后会返回一个新函数,新函数就叫做装饰器,一般为了简化装饰器会用语法糖@新函数来简化 例子: 这是一段代码,但功能太少,要对这 ...

  6. vue列表渲染中key的作用_vue中:key的作用

    因为不理解 :key(v-bind:key),网上查了一些的资料,这篇写得非常不错,很简洁清楚. 其实不只是vue,react中在执行列表渲染时也会要求给每个组件添加上key这个属性. 要解释key的 ...

  7. rono在oracle的作用_oracle中prior关键字的作用

    oracle树中prior的用法 在oracle生成树时,prior起了至关重要的作用,它决定了书的遍历方向.下面用例子分别阐述之: 1.prior放在子节点方向 (所谓子节点方向是指关联字段中作为子 ...

  8. pcie扰码的作用_CDMA中扰码的作用

    Q:要分上行和下行链路来考虑: 扰码就是就是用一个伪随机码序列对扩频码进行相乘,对信号进行加密.上行链路物理信道加扰的作用是区分用户,下行链路加扰可以区分小区和信道. 在上行链路中,扰码区分用户,扩频 ...

  9. java中static关键字的作用(java中static关键字的作用)

    关键字static的作用是什么? 在Java语言中,static表示"全局"或者"静态"的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但 ...

最新文章

  1. Clip Studio Paint 高级着色学习教程
  2. ios 添加block 类别_ios之Block的详细使用和具体说明
  3. 通过数组名遍历整个数组
  4. 如何在windows下使用linux命令
  5. Eclipse安装git插件EGit
  6. excel两个表格数据对比_Office 2010如何在桌面显示两个独立Excel表格
  7. Java之路:this关键字的用法
  8. 积微论坛--用微生物组时序数据重现生物膜装配动态过程PPT对应的讲解和提问
  9. infinitescroll php,WordPress: 增加无限分页(Infinite Scroll)功能
  10. mysql日期函_mysql日期函数
  11. 《跑跑卡丁车》国内运营商裁员超30%
  12. Python类的私有属性
  13. Spring事务和事务传播机制
  14. Halcon一维码识别实例
  15. window引导配置bcdedit
  16. 网站漏洞整改报告公司之攻防方案
  17. Thinkphp5生成二维码
  18. ios传值给js_深入剖析 iOS 与 JS 交互
  19. J2ME移动开发平台搭建
  20. 优惠券有什么用,为什么不直接降价呢?

热门文章

  1. mysql 查看锁表日志_MYSQL 表锁情况查看
  2. fedora 不在sudoers文件中_COPR 仓库中 4 个很酷的新软件(2019.4) | Linux 中国
  3. python爬虫需要什么知识-学习Python爬虫技术,需要掌握哪些web端的知识?
  4. 电脑投屏软件哪个好_目前当贝市场中投屏软件哪个好,最全面投屏技巧盘点
  5. python爬虫反爬机制_Python Scrapy突破反爬虫机制(项目实践)
  6. openMVS-编译
  7. gerber文件怎么导贴片坐标_利用Gerber文件生成贴片坐标及元件位置图的方法技巧...
  8. 两种大小端判断的方式
  9. 单调栈 leetcode整理(三)
  10. Opencv实现利用滑动条来调整阈值