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.pswp.cn/news/385777.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/385777.shtml
英文地址,請注明出處:http://en.pswp.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,較高…