android tag的作用,Android中的Context的作用(2)

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】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/385777.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

企业级项目实战讲解!javamap排序规则

一、服务发布简介 分布式系统架构下,服务发布是一件很麻烦的事情,特别是在构建自动发布流程和灰度测试的策略两个核心方面。通常情况下如果不涉及数据层面的灰度流程,服务可以灰度上线,或者滚动上线,这两种方式很常用…

android页面设置背景图片大小,android页面设置background为图片后,页面滑动掉帧问题...

最近接手的一个android项目里面,有个viewpager3个fragment的页面,就是很常见的可以左右滑动切换页面的那种布局。接手的时候告诉我,这个页面有卡顿现象,性能需要优化。一开始觉得是fragment里面做了太多耗时操作的原因&#xff0c…

企业级项目实战讲解!java的war包能直接改名么

Java核心架构笔记大致如下 0~1年: Java基础(基本语法、面向对象、继承、多态、接口和抽象类、异常、内部类、集合、泛型、反射、I/O等)Web编程(ServletMySQL数据库商品管理系统实战)SSM框架入门到精通(Sp…

android chrome cast,有了它 任何安卓设备瞬间变身ChromeCast

ChromeCast一经问世就颇受欢迎,虽然35美刀的价格已经很便宜了,但现在你可以不花一分钱就可以拥有ChromeCast类似的功能了。前提是你有一部系统版本在2.2以上的安卓设备,对于很多安卓的玩家这应该不是什么问题。实现与ChromeCast类似的功能只需…

企业级项目实战讲解!java类内部定义枚举

蚂蚁一面 ⼀⾯就做了⼀道算法题,要求两⼩时内完成,给了⻓度为N的有重复元素的数组,要求输出第10⼤的数。典型的TopK问题,快排算法搞定。算法题要注意的是合法性校验、边界条件以及异常的处理。另外,如果要写测试⽤例&…

荣耀鸿蒙价格,荣耀40S秀肌肉,120Hz+双5000万+鸿蒙系统,售价很感人

原标题:荣耀40S秀肌肉,120Hz双5000万鸿蒙系统,售价很感人虽然现在有不少的手机厂商开始发展子品牌,比如vivo发展的iQOO以及OPPO发展的真我,都是在市场上开始冒头。不过知名度最高的还是荣耀这个子品牌,自从…

作为Java开发程序员,中科创达java应届生薪资

01 并发宝典:面试专题 面试专题分为四个部分,分别如下 Synchronized 相关问题 可重入锁 ReentrantLock 及其他显式锁相关问题 Java 线程池相关问题 Java 内存模型相关问题 1.1 Synchronized 相关问题(这里整理了八问) 问题一…

Java面试必备的集合源码详解,砥砺前行!

一面(一个小时左右) 算法:写冒泡排序,问如何优化,简单讲了快排和堆排序的原理数据库:解释左连接数据库第一第二第三范式,数据库死锁linux:怎么查看内存;怎么查看进程&am…

android md 控件,Android基本UI控件.md

# Android基本UI控件## *TextView 文本框*### TextView常用用法| 主要方法 | 功能描述 || :----------: | :--------------------: || getText | 获得TextView对象的文本 || setText | 设置TextView对象的文本 || setTextColor | 设置文本显示的颜色 |Javaprivate TextView tex…

java面试核心知识点,详解系列文章

技术能力 通常,「技术能力」这个部分将紧接着你的个人简介之后,放在简历的核心版面。这样设计是有道理的,因为它能够帮助雇主更快的判断你的技能是否与需求相吻合。 因此在制作这一部分内容时,你应该考虑以下两点: …

html5跨平台桌面打包,Html5到跨平台app应用

Html5到跨平台app应用每一项新兴技术的出现和流行,都是为了规模化的去统一解决一系列复杂问题,APICloud选择混合开发方向,目的是希望借助HTML5降低app开发复杂度,提高app开发效率。通过工程化的实践手段,我们首先设计了…

Java面试知识点总结宝典助你通关!成功入职字节跳动

01 阿里中间件(四面,Java岗) 1.1 Java中间件一面 技术一面考察范围 重点问了Java线程锁:synchronized 和ReentrantLock相关的底层实现 线程池的底层实现以及常见的参数 数据结构基本都问了一遍:链表、队列等 Java内存…

html第二章课后选择题答案,HTML课后习题(带答案).doc

HTML课后习题选择题1. 下列标签中,用于设置字体大小、颜色的标签是(D)A. bB. subC. supD. font关于下列代码片段,说法错误的是(A)A. 用于在HTML文档中插入图像链接B. 图像以100100的大小显示C. 标签用于在页面中显示一张图像D. 图像的对齐方式为左对齐3.…

那些年的随笔

平安夜,没有下雪,也不冷,也没有女朋友。不知道来年是否会幸福。 单身这么多年,工作这么多年,知道了孤独,知道了辛苦,知道了人情冷暖。 我们每个人都有着自己的幸福选择。有的人追寻着此时此刻…

Java面试题及答案,java入门书籍

天下码农,多为CV!你是否每天还在增删改查?性能优化让你手足无措?看这里!技术大牛带你分分钟完爆性能优化!!! Java性能权威指南淘宝千万并发性能优化实战!理论结合实战&am…

隐藏导航条HTML,jQuery实现的导航条切换可显示隐藏

用jQuery实现一些导航条切换,显示隐藏,主要运用的技术有slideToggle( ),toggeClass( ),toggle( ):代码如下:导航条在项目中的应用$(function(){$(".tit").find("span").click(function(){$(this).…

Java面试题库,java用tabula解析pdf表格

Java代码是怎么运行的? Java的基本类型 Java虚拟机是如何加载Java类的 JVM是如何执行方法调用的?(上) JVM是如何执行方法调用的?(下) JVM是如何处理异常的? JVM是如何实现反射的&…

idea中HTML可以打debug吗,Intellij IDEA中使用Debug调试

virtual关键字的本质是什么?MSDN上对virtual方法的解释:试着翻译如下 当一个方法声明包含virtual修饰符,这个方法就是虚方法.如果没有virtual修饰符,那么就不是虚方法. 非虚方法的实现是不变的:不管该方法是被 ...kafka java代码实现消费者public class KafkaConsum…

Java面试题:kafka幂等性+事务

一面: hashmap,怎么扩容,怎么处理数据冲突?怎么高效率的实现数据迁移?Linux的共享内存如何实现,大概说了一下。Linux 中的用户模式和内核模式是什么含意?在 Java 中 Lock 接口比 synchronized 块的优势是…

计算机网络与网站设计知识点,计算机网络技术知识点总结-20210525075410.docx-原创力文档...

计算机网络技术知识点总结计算机网络技术知识点总结计算机网络技术重点总结局域网是一种小范围(几公里)的以实现资源共享为基本目的而组建的计算机网络,其本质特征是分布距离短、数据传输速度快。较低速的局域网传输数据的速度大约为10Mb/s~100Mb/s,较高…