編輯:關於Android編程
一個Context意味著一個場景,一個場景就是我們和軟件進行交互的一個過程。比如當你使用微信的時候,場景包括聊天界面、通訊錄、朋友圈,以及背後的一些數據。
那麼從程序的角度來看,Context是什麼?其實一個Activity就是一個Context,一個Service也是一個Context。
一個應用程序可以認為是一個工作環境,用戶在這個工作環境中會切換到不同的場景,這就像一個助理,他可能需要接待客人,可能還要打印文件,還可能接聽電話,而這些就稱之為不同的場景,助理可稱之為一個應用程序。
Activity類的確是基於Context,而Service類也是基於Context。Activity除了基於Context類外,還實現了一些其他重要的接口,從架構設計的角度看,interface僅僅是某些功能,而extends才是類的本質,即Activity的本質是一個Context,其所實現的其他接口只是為了擴充Context的功能而已,擴充後的類稱之為一個Activity或Service。
我們在應用程序開發中經常會調用Context的一些方法,這些方法看起來似乎會返回一些全局的對象,而不僅僅是某個Activity,可能會有點疑問,一個應用程序到底有多少個Context對象呢?比如,Context.getResources()返回該應用程序所對應的Resource類對象,無論從哪個Activity中調用,都會返回同一個Resource對象。
一個Activity就是一個場景(Context),一個Service也是一個場景,所以,應用程序中有多少個Activity或者Service就會有多少個Context對象。 getResource()等方法返回的是同一個全局對象。Context類本身是一個純abstract類。為了使用方便又定義了Context包裝類-ContextWrapper,ContextWrapper構造函數中必須包含一個真正的Context引用,同時ContextWrapper中有attachBaseContext()用於給ContextWrapper對象中指定真正的Context對象。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPkNvbnRleHRUaGVtZVdyYXBwZXLE2rK/sPy6rMHL0+vW98ziz+C52LXEvdO/2qOs1eLA77XE1vfM4r7NysfWuNTaQW5kcm9pZE1hbmlmZXN0LnhtbNbQzai5/WFuZHJvaWSjunRoZW1lzqpBcHBsaWNhdGlvbrvy1d9BY3Rpdml0eda4tqi1xNb3zOKhozwvcD4NCjxwPta709BBY3Rpdml0ebLF0OjSqtb3zOKjrFNlcnZpY2Wyu9Do0qrW98zitcSjrMv50tRTZXJ2aWNl1rG907zMs9DT60NvbnRleHRXcmFwcGVyoaM8L3A+DQo8cD5Db250ZXh0SW1wbMDg1ebV/cq1z9bBy0NvbnRleHTW0Mv509C1xLqvyv2jrM7Sw8fL+bX308O1xLj31tZDb250ZXh0wOC1xLe9t6jG5Mq1yrXP1r75wLTX1NPauMPA4KGjPC9wPg0KPGgyIGlkPQ=="什麼時候創建context">什麼時候創建Context?
每一個應用程序在客戶端都是從ActivityThread類開始的,創建Context對象也是在該類中完成,具體創建ContextImpl類的地方一共有6處:
PackageInfo.makeApplication() performLaunchActivity() handleCreateBackupAgent() handleCreateService() handleBindApplication() attach()其中attach()方法僅在Framework進程啟動時調用,應用程序運行時不會調用到該方法。
程序第一次啟動時,會輾轉調用到makeApplication()方法。具體代碼如下:
ContextImpl appContext = new ContextImpl();
appContext.init(this,null,mActivityThread);
....
appContext.setOuterContext(app);
啟動Activity時,Ams會通過IPC調用到ActivityThread的scheduleLaunchActivity()方法,該方法包含兩種參數。一種是ActivityInfo,這是一個實現了Parcelable接口的數據類,意味著該對象是Ams創建的,並通過IPC傳遞到ActivityThread;另一種是其他的一些參數。
scheduleLaunchActivity()方法中會根據以上兩種參數構造一個本地ActivityRecord數據類,ActivityThread內部會為每一個Activity創建一個ActivityRecord對象,並使用這些數據對象來管理Activity。
然後會調用handleLaunchActivity(),再調用performLaunchActivity(),該方法中創建ContextImpl的代碼如下:
ContextImpl appContext = new ContextImpl();
appContext.init(r.packageInfo,r.token,this);
appContext.setOuterContext(activity);
在performLaunchActivity()開始執行時,會為r.packageInfo變量賦值。r.packageInfo對象的PackageInfo對象和Application對應的packageInfo對象是同一個。
啟動Service時,Ams會通過IPC調用到ActivityThread的scheduleCreateService()方法,該方法也包含兩種參數。第一種是ServiceInfo,這是實現了一個Parcelable接口的數據類,該對象由AmS創建,並通過IPC傳遞到ActivityThread內部;第二種是其他參數。
在scheduleCreateService()方法中,會使用以上兩種參數構造一個CreateServiceData的數據對象,ActivityThread會為其所包含的每一個Service創建該數據對象,並通過這些對象來管理Service。
然後在執行handleCreateService()方法,創建ContextImpl對象代碼如下:
ContextImpl appContext = new ContextImpl();
appContext.init(packageInfo,null,this);
...
appContext.setOuterContext(service);
Service對應的Context對象內部的mPackageInfo與Activity、Application中是完全相同的。
從以上可以看出,創建Context對象的過程基本上是相同的,不同的僅僅是針對Application、Activity、Service使用了不同的數據對象。
一個應用程序包含的Context個數應該為:Context個數 = Service個數+Activity個數+1,最後的1是Application類本身也會對應一個Context對象。
應用程序中包含多個ContextImpl對象,而內部變量mPackageInfo卻指向同一個PackageInfo對象,這種設計結構一般意味著ContextImpl是一種輕量級類,而PackageInfo是一個重量級類。事實上確實是這樣,ContextImpl中的大多數進行包操作的重量級函數實際上都是轉向了mPackageInfo對象相應的方法,也就是事實上調用了同一個PackageInfo對象。
參考:https://developer.android.com/training/material/lists-cards.html1、簡介RecyclerView已經
學會了Paint,Canvas的基本用法之後,我們就可以動手開始實踐了,先寫個簡單的圖片加載進度條看看。 按照慣例,先看效果圖,再決定要不要往下看:既然看到這裡了,應該是
在android開發中,經常用到去解析xml文件,常見的解析xml的方式有一下三種:SAX、Pull、Dom解析方式。最近做了一個android版的CSDN閱讀器,用到了
java虛擬機基本結構:JVM是一個內存中的虛擬機,那它的存儲就是內存了,我們寫的所有類、常量、變量、方法都在內存中,因此明白java虛擬機的內存分配非常重要,本部分主要