摘要:關(guān)于后稱的操作我們知道其實(shí)就是文件,所以這里的操作有獲取移動(dòng)刪除。操作啟動(dòng)停止重啟綁定解綁獲取系統(tǒng)服務(wù)以及多用戶操作。權(quán)限操作檢查本是否有某種權(quán)限檢查某是否有某種權(quán)限檢查權(quán)限授予權(quán)限等等。
先放一張圖吧 2.用處
1.Context的實(shí)現(xiàn)類有很多,但是ContextImpl(后稱CI)是唯一做具體工作的,其他實(shí)現(xiàn)都是對(duì)CI做代理。
2.CI中有一些成員對(duì)象,先來看看這些對(duì)象的用處
1.mSharedPrefsPaths(ArrayMap
2.mMainThread(ActivityThread(后稱AT)):這個(gè)對(duì)象是一個(gè)app進(jìn)程的主線程,一個(gè)app的framework層就是從這里啟動(dòng)的。
3.mPackageInfo(LoadedApk(后稱LA)):在AT初始化app的主線程的時(shí)候,會(huì)將APK加載到內(nèi)存中,apk在內(nèi)存中就是以這個(gè)對(duì)象的形式存在的,該對(duì)象可以加載apk的資源和dex文件。
4.mUser(UserHandle):多用戶相關(guān)
5.mContentResolver(ApplicationContentResolver):繼承于ContentResolver(后稱CR),主要功能是通過Uri來獲取文件、數(shù)據(jù)庫、asset、res等數(shù)據(jù),還有就是通過ContentProvider來獲取其他應(yīng)用和本機(jī)數(shù)據(jù)。
6.mResourcesManager(ResourcesManager):單例,因?yàn)橐粋€(gè)apk不同機(jī)型的適配資源,所以用來加載Resource對(duì)象,以保證一個(gè)app中所有的CI使用的都是同一份資源。
7.mResources(Resources):獲取apk中res資源的對(duì)象。
8.mOuterContext(Context):用于指向代理本對(duì)象的Context,例如Activity、Service等
9.mTheme(Resources.Theme):主題
10.mPackageManager(PackageManager(后稱PM)):包管理類,不僅可以獲取我們apk包的信息,還能獲取本機(jī)apk包的信息。
3.CI中有很多api,我將這些api歸了一下類
1.獲取成員對(duì)象:即獲取上面我列出來的那些對(duì)象,這些對(duì)象獲取到了之后又有更多api暴露出來,在這里CI相當(dāng)于做了一個(gè)聚合。最常用的就是getResource()了。
2.獲取成員對(duì)象的成員對(duì)象:即為了方便,CI封裝了一些常用的獲取成員對(duì)象中的信息的方法。例如getPackageName(),是通過PM來獲取的。
3.關(guān)于SharedPreferences(后稱SP)的操作:我們知道SP其實(shí)就是xml文件,所以這里的操作有:獲取、移動(dòng)、刪除。
4.文件操作:增刪移文件、打開文件流、獲取app私有文件夾地址等等。
5.數(shù)據(jù)庫操作:我們知道sqlite其實(shí)是一種文件型數(shù)據(jù)庫,所以有:打開、創(chuàng)建、移動(dòng)、刪除、獲取數(shù)據(jù)庫文件路徑,等操作。
6.壁紙相關(guān)操作:這個(gè)不是成員變量提供的,WallpaperManager是系統(tǒng)Service一種,所以是SystemService提供的。
7.啟動(dòng)Activity:包括一般啟動(dòng)Acitivyt、多用戶啟動(dòng)Activity、啟動(dòng)多個(gè)Activity。
8.廣播操作:發(fā)送普通廣播、發(fā)送需要權(quán)限的廣播、發(fā)送有序廣播、發(fā)送粘連廣播、發(fā)送有序粘連廣播、多用戶廣播、移除各種廣播、注冊(cè)各種廣播、取消注冊(cè)各種廣播。
9.Service操作:啟動(dòng)、停止、重啟、綁定、解綁、獲取系統(tǒng)服務(wù)以及多用戶操作。
10.權(quán)限操作:檢查本app是否有某種權(quán)限、檢查某app是否有某種權(quán)限、檢查Uri權(quán)限、授予權(quán)限等等。
11.各種情況下創(chuàng)建CI:這個(gè)比較重要
1.createSystemContext(ActivityThread mainThread):在SystemService創(chuàng)建的時(shí)候?yàn)槠鋭?chuàng)建一個(gè)CI
2.createAppContext(ActivityThread mainThread, LoadedApk packageInfo):在Application/Service創(chuàng)建的時(shí)候?yàn)槠鋭?chuàng)建一個(gè)CI
3.createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, IBinder activityToken, int displayId,
Configuration overrideConfiguration):在Activity創(chuàng)建的時(shí)候?yàn)槠鋭?chuàng)建一個(gè)CI。
在了解Binder的時(shí)候有如下要注意的點(diǎn)
1.Activity初始化:
1.CI.startActivity():將調(diào)用交給Instrumentation(負(fù)責(zé)監(jiān)控Activity和AMS的交互,所有Activity的本地進(jìn)程到遠(yuǎn)端進(jìn)程的調(diào)用轉(zhuǎn)換都是其來執(zhí)行),
2.Instrumentation.execStartActivity():傳入一個(gè)ApplicationThread(后稱APT)然后通過Binder機(jī)制將調(diào)用過程轉(zhuǎn)移到ActivityManagerService(后稱AMS)所在的系統(tǒng)服務(wù)進(jìn)程,本地主線程則繼續(xù)運(yùn)行,不過本地主線程后續(xù)也沒別的操作了,接下來就是本地的MessageQueue等待AMS服務(wù)運(yùn)行完畢,發(fā)送消息將Activity的啟動(dòng)重新交給本地主線程。
3.AMS.startActivity():從這里開始會(huì)調(diào)用會(huì)按順序在 ActivityStarter、ActivityStackSupervisor、ActivityStack 這三個(gè)類之間進(jìn)行調(diào)用,主要會(huì)進(jìn)行下面這些操作,不按順序:
1.對(duì)Intent的內(nèi)容進(jìn)行解析,獲取目標(biāo)Activity的信息。
2.根據(jù)傳入的APT獲取被調(diào)用app的信息封裝成 ProcessRecord(后稱PR)。
3.將1、2和其他信息結(jié)合,將源Activity和目標(biāo)Activity封裝成兩個(gè)ActivityRecord(后稱AR)
4.解析Activity的啟動(dòng)模式 和當(dāng)前的Activity棧狀態(tài),判斷是否需要?jiǎng)?chuàng)建棧和Activity。(注意這里的AR有著app中的Activity的全部信息,可以將其看成系統(tǒng)服務(wù)里面的Activity的化身)
5.獲取到Activity和Activity棧之后,接下來要判斷是否要將當(dāng)前Activity 執(zhí)行onPause() 以及讓使用Binder執(zhí)行目標(biāo)Activity的 onCreate()和onResume(注意這里onStart()會(huì)在Binder遠(yuǎn)程調(diào)用onCreate()的時(shí)候直接執(zhí)行),這里AMS進(jìn)程會(huì)使用APT調(diào)用app進(jìn)程的Activity執(zhí)行相應(yīng)的生命周期。
6.在AMS中前置準(zhǔn)備一切就緒之后,會(huì)通過APT使用Handler的形式調(diào)用到app進(jìn)程的AT中。
7.最終到了ActivityStackSupervisor.realStartActivityLocked()中會(huì)使用APT將調(diào)用交給app進(jìn)程-->AT.scheduleLaunchActivity()-->AT.handleLaunchActivity()
4.AT.handleLaunchActivity():將有以下操作
1.AT.performLaunchActivity:這個(gè)方法有以下操作
1.創(chuàng)建對(duì)象LoadedApk(后稱LA,一個(gè)app只加載一次)
2.創(chuàng)建對(duì)象Activity
3.創(chuàng)建對(duì)象Application(一個(gè)app,只創(chuàng)建一次)
4.創(chuàng)建對(duì)象CI:CI.createActivityContext()
5.Application/CI都attach到Activity對(duì)象:Activity.attach()
6.執(zhí)行onCreate():Instrumentation.callActivityOnCreate()-->Activity.performCreate()-->Activity.onCreate()
7.執(zhí)行onStart():AT.performLaunchActivity-->Activity.performStart()-->>Instrumentation.callActivityOnStart()—>Activity.onStart()
2.AT.handleResumeActivity()
1.AT.performResumeActivity()-->Activity.performResume()-->Instrumentation.callActivityOnResume()-->Activity.onResume()
2.Activity.makeVisible()-->WindowManager.addView():開始進(jìn)行View的繪制流程。
3.從上面我們可以總結(jié)一下:在AMS將調(diào)用交給app進(jìn)程之后,三個(gè)生命周期都是在app進(jìn)程被回調(diào)的,并且在onResume()之后View才進(jìn)行繪制
2.Service初始化:
1.CI.startService()-->CI.startServiceCommon():在這里傳入一個(gè)APT,類似Activity啟動(dòng)時(shí)的第二步,將調(diào)用過程轉(zhuǎn)移到AMS中,本地主線程繼續(xù)運(yùn)行,等待APT從AMS進(jìn)程將調(diào)用轉(zhuǎn)移到本地主線程中。
2.AMS.startService():到了AMS進(jìn)程之后,Service的啟動(dòng)就會(huì)全權(quán)交給ActiveServices(后稱AS,這是AMS用來管理Service的成員變量)
3.AS.startServiceLocked():這里做了以下操作
1.根據(jù)傳入的APT獲取被調(diào)用app的信息封裝成 PR
2.解析Intent等參數(shù)獲取到Service的信息,封裝成ServicecRecord(后稱SR,這個(gè)類可以看做是Service在系統(tǒng)服務(wù)的化身,記錄了Service的一切信息)
3.再進(jìn)過一系列調(diào)用:AS.startServiceInnerLocked()-->AS.bringUpServiceLocked()-->AS.realStartServiceLocked()到這里才是真正在app進(jìn)程啟動(dòng)Service的流程。
4.AS.realStartServiceLocked():這里會(huì)有以下操作:
1.SR.thread.scheduleCreateService():thread就是APT,這里會(huì)將調(diào)用轉(zhuǎn)到app進(jìn)程,但是當(dāng)前的進(jìn)程還會(huì)繼續(xù)執(zhí)行,這里就到了app線程的APT,這個(gè)方法里有以下操作
1.通過Handler轉(zhuǎn)到AT.handleCreateService()
2.創(chuàng)建對(duì)象LA(一個(gè)app只加載一次)
3.創(chuàng)建對(duì)象Service
4.創(chuàng)建對(duì)象CI
5.創(chuàng)建對(duì)象Application(一個(gè)app只創(chuàng)建一次)
6.Application/CI分別attach到Service對(duì)象
7.執(zhí)行Service.onCreate()回調(diào)
8.此時(shí)Service已經(jīng)啟動(dòng)了
2.AS.sendServiceArgsLocked()-->SR.app.thread.scheduleServiceArgs():這里就轉(zhuǎn)到了app進(jìn)程的APT中,這里會(huì)有以下操作:
1.APT.scheduleServiceArgs()
2.AT.handleServiceArgs()
3.Service.onStartCommand()
4.此時(shí)我們需要在Service中進(jìn)行的操作將會(huì)執(zhí)行。
3.ContentProvider初始化:
1.AT.main()-->AT.attach()-->AMS.attachApplication():傳入一個(gè)APT,調(diào)用轉(zhuǎn)到了AMS進(jìn)程
2.AMS.attachApplicationLocked():獲取到ApplicationInfo 和 ProviderInfo列表之后通過APT將調(diào)用轉(zhuǎn)回app進(jìn)程。
3.APT.bindApplication()-->AT.handleBindApplication()-->AT.installContentProviders():到這里之后將會(huì)循環(huán)初始化ContentProvider。
4.AT.installProvider():這個(gè)方法里面有以下操作
1.創(chuàng)建對(duì)象LA:CI.createPackageContext()中
2.創(chuàng)建對(duì)象CI:CI.createPackageContext()中
3.創(chuàng)建對(duì)象ContentProvider:ClassLoader創(chuàng)建
4.CI attach到ContentProvider對(duì)象:ContentProvider.attachInfo()中
5.執(zhí)行onCreate回調(diào):ContentProvider.attachInfo()中
4.BroadCastReceiver靜態(tài)初始化:因?yàn)閯?dòng)態(tài)廣播的注冊(cè)時(shí)進(jìn)程已創(chuàng)建, 基本對(duì)象已創(chuàng)建完成,只需要回調(diào)BroadcastReceiver的onReceive()方法即可,所以這里不分析
1.當(dāng)收到廣播時(shí)會(huì)調(diào)用AT.handleReceiver()
2.創(chuàng)建對(duì)象LA(一個(gè)app只加載一次)
3.創(chuàng)建對(duì)象BroadcastReceiver
4.創(chuàng)建對(duì)象Application
5.從創(chuàng)建的Application中獲取CI
6.執(zhí)行onReceive()回調(diào)
5.Application初始化:由上面四個(gè)組件的初始化我們可以知道,當(dāng)app還沒啟動(dòng)的時(shí)候喚醒任意組件都會(huì)創(chuàng)建一個(gè)Application,而這里分析的是正常情況啟動(dòng)一個(gè)app的時(shí)候創(chuàng)建Application的流程。
1.這里的流程其實(shí)就是包含了ContentProvider初始化的流程,所以前面都差不多
2.最后到了AT.handleBindApplication()中,這里有以下操作:
1.創(chuàng)建對(duì)象LA
2.創(chuàng)建對(duì)象CI
3.創(chuàng)建對(duì)象Instrumentation
4.創(chuàng)建對(duì)象Application;
5.安裝providers
6.執(zhí)行Create回調(diào)
4.四大組件以及Application綁定Context的方法由上一節(jié)我們可以知道,四大組件以及Application在初始化的時(shí)候都會(huì)進(jìn)行Context的綁定或者創(chuàng)建,這節(jié)就來講講各個(gè)組件是如何對(duì)context進(jìn)程賦值的。
1.Activity:
1.AT.performLaunchActivity()
2.AT.createBaseContextForActivity(ActivityClientRecord , Activity)
3.ContextImpl.createActivityContext(ActivityThread , LoadedApk , IBinder , int displayId , Configuration)
4.ContextImpl():被賦值了 ActivityThread、LoadedApk、IBinder activityToken、Configuration
2.Service/Application:
1.AT.handleCreateService()
2.ContextImpl.createAppContext(ActivityThread , LoadedApk)
3.new ContextImpl():被賦值了 ActivityThread、LoadedApk
3.BroadCastReceiver:在AT.handleReceiver()中直接獲取Application的Context,其自身并不創(chuàng)建Context
4.ContentProvider:
1.AT.installProvider()
2.Context.createPackageContext()-->CI.createPackageContext()-->CI.createPackageContextAsUser():這里是通過一個(gè)Application的Context創(chuàng)建的Context,所以可以看做是Application的Context的一個(gè)復(fù)制。
5.總結(jié) 1.組件初始化會(huì)創(chuàng)建的對(duì)象:1.LoadedApk:所有組件在初始化的時(shí)候,如果LA沒被初始化都會(huì)初始化一遍
2.Context:
1.只有Activity的CI有上一個(gè)Activity的Token
2.Receiver的Context是繼承于ContextWrapper 的 ReceiverRestrictedContext,不可綁定Service。
3.Application:
1.Receiver使用的Context是ReceiverRestrictedContext包裝的Application的Context,所以其可以通過Context獲取到Application
2.ContentProvider一般是在app初始化的時(shí)候在初始化Application的過程中加載的,此時(shí)Application會(huì)被加載。但是如果是多個(gè)app共享進(jìn)程,第二個(gè)app由ContentProvider調(diào)起,那么Application不會(huì)被初始化。
2.Context使用場景說明: (圖中第一列代表不同的Context, √代表允許在該Context執(zhí)行相應(yīng)的操作; ×代表不允許; -代表分情況討論)
1.當(dāng)Context為Receiver的情況下:
1.不允許執(zhí)行bindService()操作, 由于限制性上下文(ReceiverRestrictedContext)所決定的,會(huì)直接拋出異常.
2.registerReceiver是否允許取決于receiver;
3.當(dāng)receiver == null用于獲取sticky廣播, 允許使用;否則不允許使用registerReceiver;
2.縱向來看startActivity操作
1.當(dāng)為Activity Context則可直接使用;
2.當(dāng)為其他Context, 要啟動(dòng)的Activity不屬于任何Activity棧,所以必須帶上FLAG_ACTIVITY_NEW_TASK flags才能使用
3.getApplication()和getApplicationContext()絕大多數(shù)情況下, getApplication()和getApplicationContext()這兩個(gè)方法完全一致, 返回值也相同; 那么兩者到底有什么區(qū)別呢? 真正理解這個(gè)問題的人非常少. 接下來徹底地回答下這個(gè)問題:
1.getApplicationContext()這個(gè)的存在是Android歷史原因. 我們都知道getApplication()只存在于Activity和Service對(duì)象; 那么對(duì)于BroadcastReceiver和ContentProvider卻無法獲取Application, 這時(shí)就需要一個(gè)能在Context上下文直接使用的方法, 那便是getApplicationContext().
2.對(duì)于Activity/Service來說, getApplication()和getApplicationContext()的返回值完全相同; 除非廠商修改過接口;
3.BroadcastReceiver在onReceive的過程, 能使用getBaseContext().getApplicationContext獲取所在Application, 而無法使用getApplication;
4.ContentProvider能使用getContext().getApplicationContext()獲取所在Application. 絕大多數(shù)情況下沒有問題, 但是有可能會(huì)出現(xiàn)空指針的問題, 情況如下:當(dāng)同一個(gè)進(jìn)程有多個(gè)apk的情況下, 對(duì)于第二個(gè)apk是由provider方式拉起的, 前面介紹過provider創(chuàng)建過程并不會(huì)初始化所在application, 此時(shí)執(zhí)getContext().getApplicationContext()返回的結(jié)果便是NULL. 所以對(duì)于這種情況要做好判空.
作者:何時(shí)夕
鏈接:https://www.jianshu.com/p/f49...
近3年BAT面試真題整理合集
?一招教你讀懂JVM和Dalvik之間的區(qū)別
金9銀10的面試黃金季節(jié),分享幾個(gè)重要的面試題
kotlin學(xué)習(xí)筆記-異常好玩的list集合總結(jié)
相信自己,沒有做不到的,只有想不到的在這里獲得的不僅僅是技術(shù)!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/76580.html
摘要:作為的四大組件之二,其應(yīng)用場景非常多。作用可以監(jiān)聽或接收應(yīng)用或系統(tǒng)發(fā)出的廣播消息,并做出響應(yīng)。可以指定獨(dú)立的進(jìn)程四大組件都可以通過此屬性指定自己的獨(dú)立進(jìn)程。對(duì)于應(yīng)用內(nèi)廣播的動(dòng)態(tài)注冊(cè)方式,回調(diào)中的返回值是。 前言 Hi,大家好,又雙見面啦,上一期我們講了如何使用Activity,肯定有不少小伙伴已經(jīng)創(chuàng)建了屬于自己的FirstActivity,那么這一期我們主要為大家介紹第二個(gè)重要組件Br...
摘要:方法,是一個(gè)對(duì)象是從構(gòu)造函數(shù)中賦值。上面我們分析到會(huì)執(zhí)行構(gòu)造函數(shù),在構(gòu)造函數(shù)會(huì)將的賦值給的。傳入的是返回對(duì)象也是繼承,其是。參考插件化技術(shù)原理篇中詳解你所不知道的更深層次的理解 Android插件化在國內(nèi)已不再是幾個(gè)巨頭公司團(tuán)隊(duì)在玩了,陸續(xù)有團(tuán)隊(duì)開源其解決方案,例如 Small,VirtualAPK,RePlugin,Atlas,甚至Lody開發(fā)的VirtualApp。另外我司也在玩,...
摘要:但是,一定會(huì)被執(zhí)行,從而保證了廣播在死亡前一定會(huì)被注銷,從而防止內(nèi)存泄露。對(duì)于應(yīng)用內(nèi)廣播的動(dòng)態(tài)注冊(cè)非方式,回調(diào)中的返回值是 前言 BroadcastReceiver(廣播接收器),屬于Android四大組件之一 在Android開發(fā)中,BroadcastReceiver的應(yīng)用場景非常多 今天,我將詳細(xì)講解關(guān)于BroadcastReceiver的一切相關(guān)知識(shí) 目錄 showImg(...
閱讀 3091·2023-04-25 15:44
閱讀 1876·2019-08-30 13:11
閱讀 2830·2019-08-30 11:11
閱讀 3004·2019-08-29 17:21
閱讀 1306·2019-08-29 15:38
閱讀 898·2019-08-29 12:49
閱讀 1793·2019-08-28 18:19
閱讀 3222·2019-08-26 14:01