季充分组件和Application和Context的统筹兼顾掌握

1.概述

Context抽象结构

2.用处

  • 1.Context之实现类似闹好多,但是ContextImpl(后称CI)是唯一做实际工作的,其他实现都是对准CI做代办。
  • 2.CI蒙受发生一部分分子对象,先来探这些目标的用途
    • 1.mSharedPrefsPaths(ArrayMap<String,
      File>)、sSharedPrefsCache(ArrayMap<String,
      ArrayMap<File,
      SharedPreferencesImpl>>):这片独对象是用于取SharedPreferences的,在自己前一模一样首博客里有曰到。全盘剖析SharedPreferences
    • 2.mMainThread(ActivityThread(后称AT)):这个目标是一个app进程的主线程,一个app的framework层就是起这里启动之。
    • 3.mPackageInfo(LoadedApk(后称LA)):在AT初始化app的主线程的时,会以APK加载到外存中,apk于内存中就是是坐之目标的款式有的,该目标可以加载apk的资源和dex文件。
    • 4.mUser(UserHandle):多用户相关
    • 5.mContentResolver(ApplicationContentResolver):继承于ContentResolver(后称CR),主要意义是透过Uri来赢得文件、数据库、asset、res等数据,还有即使是通过ContentProvider来获取其它使用与本机数据。
    • 6.mResourcesManager(ResourcesManager):单例,因为一个apk不同机型的适配资源,所以用来加载Resource对象,以管教一个app中享有的CI使用的还是平客资源。
    • 7.mResources(Resources):获取apk中res资源的靶子。
    • 8.mOuterContext(Context):用于因为代理本对象的Context,例如Activity、Service等
    • 9.mTheme(Resources.Theme):主题
    • 10.mPackageManager(PackageManager(后称PM)):包管理类,不仅可以获得我们apk包之音,还会获取本机apk包的音信。
  • 3.CI蒙受生众多api,我拿这些api归了一下类
    • 1.获取成员对象:即取得上面我排出来的那些对象,这些目标获得到了之后还要发出更多api暴露出,在此地CI相当给做了一个成团。最常用的即使是getResource()了。
    • 2.落成员对象的分子对象:即以有利于,CI封装了片常用的获得成员对象吃之信息之方法。例如getPackageName(),是经过PM来收获之。
    • 3.关于SharedPreferences(后称SP)的操作:我们掌握SP其实就是xml文件,所以这边的操作发生:获取、移动、删除。
    • 4.文件操作:增删移文件、打开文件流、获取app私有文件夹地址等等。
    • 5.数据库操作:我们领略sqlite其实是同样栽文件型数据库,所以有:打开、创建、移动、删除、获取数据库文件路径,等操作。
    • 6.壁纸相关操作:这个不是成员变量提供的,WallpaperManager是系Service一种,所以是SystemService提供的。
    • 7.起先Activity:包括一般启动Acitivyt、多用户启动Activity、启动多个Activity。
    • 8.广播操作:发送普通广播、发送需要权限的播报、发送有序广播、发送粘连广播、发送出次序粘连广播、多用户广播、移除各种广播、注册各种广播、取消注册各种广播。
    • 9.Service操作:启动、停止、重开、绑定、解绑、获取系统服务和多用户操作。
    • 10.权限操作:检查本app是否发生某种权力、检查某app是否发生某种权力、检查Uri权限、授予权限等等。
    • 11.各种状况下开创CI:这个比主要
      • 1.createSystemContext(ActivityThread
        mainThread):在SystemService创建的早晚啊该创建一个CI
      • 2.createAppContext(ActivityThread mainThread, LoadedApk
        packageInfo):在Application/Service创建的时光吗那个创立一个CI
      • 3.createActivityContext(ActivityThread mainThread,
        LoadedApk packageInfo, IBinder activityToken, int
        displayId,
        Configuration
        overrideConfiguration):在Activity创建的上啊该创造一个CI。

3.季坏组件和Application初始化与Context的涉及

于了解Binder的时节发出如下要小心的触及

图片

  • 1.Activity初始化:
    • 1.CI.startActivity():将调用交给Instrumentation(肩负监控Activity和AMS的彼此,所有Activity的地头进程到远端进程的调用转换都是彼来执行),
    • 2.Instrumentation.execStartActivity():传入一个ApplicationThread(后称APT)然后通过Binder机制将调用过程易到ActivityManagerService(后称AMS)所于的系服务过程,本地主线程则继续运行,不过当地主线程后续也没别的操作了,接下去就当地的MessageQueue等待AMS服务运作了,发送信息将Activity的启动重提交当地主线程。
    • 3.AMS.startActivity():从这里开会调用会按梯次以
      ActivityStarter、ActivityStackSupervisor、ActivityStack
      这三独八九不离十中展开调用,主要会展开下这些操作,不以梯次:

      • 1.对准Intent的情展开剖析,获取目标Activity的信息。
      • 2.根据传入的APT获取给调用app的音封装成
        ProcessRecord(后称PR)。
      • 3.拿1、2暨外信息整合,将源Activity和对象Activity封装成稀单ActivityRecord(后称AR)
      • 4.解析Activity之启动模式
        和目前之Activity栈状态,判断是否用创造栈和Activity。(留意这里的AR有着app中的Activity的一体信,可以拿该视作系统服务之中的Activity的化身)
      • 5.博到Activity和Activity栈之后,接下去要判是否要将眼前Activity
        执行onPause() 以及被使用Binder执行对象Activity的
        onCreate()和onResume(留意这里onStart()会以Binder远程调用onCreate()的上一直执行),这里AMS进程会采取APT调用app进程的Activity执行相应的生命周期。
      • 6.在AMS蒙放置准备全就绪后,会透过APT使用Handler的款式调用到app进程的AT中。
      • 7.末到了ActivityStackSupervisor.realStartActivityLocked()中见面使APT将调用交给app进程–>AT.scheduleLaunchActivity()–>AT.handleLaunchActivity()
    • 4.AT.handleLaunchActivity():将时有发生以下操作
      • 1.AT.performLaunchActivity:这个措施发生以下操作
        • 1.创建对象LoadedApk(后称LA,一个app只加载同糟)
        • 2.创建对象Activity
        • 3.创建对象Application(一个app,只开创同潮)
        • 4.创建对象CI:CI.createActivityContext()
        • 5.Application/CI都attach到Activity对象:Activity.attach()
        • 6.执行onCreate():Instrumentation.callActivityOnCreate()–>Activity.performCreate()–>Activity.onCreate()
        • 7.执行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():开始进行View的绘图流程。
      • 3.于地方我们可总结一下:在AMS将调用交给app进程之后,三个生命周期都是以app进程被回调的,并且在onResume()之后View才进行绘图
  • 2.Service初始化:
    • 1.CI.startService()–>CI.startServiceCommon():在此处流传一个APT,类似Activity启动时之次步,将调用过程易到AMS中,本地主线程继续运行,等待APT从AMS进程将调用转移到本地主线程中。
    • 2.AMS.startService():到了AMS进程之后,Service的启动就会全权交由ActiveServices(后称AS,这是AMS用来管理Service的分子变量)
    • 3.AS.startServiceLocked():这里开了以下操作
      • 1.冲传入的APT获取给调用app的信封装成 PR
      • 2.解析Intent相当于参数获取到Service的音信,封装成ServicecRecord(后称SR,这个近乎可以作为是Service在系统服务之化身,记录了Service的整个信息)
      • 3.重新前进过相同多级调用:AS.startServiceInnerLocked()–>AS.bringUpServiceLocked()–>AS.realStartServiceLocked()到此处才是的确当app进程启动Service的流程。
    • 4.AS.realStartServiceLocked():这里会见生以下操作:
      • 1.SR.thread.scheduleCreateService():thread就是APT,这里会以调用转到app进程,但是当前之过程还会继续执行,这里就是到了app线程的APT,这个主意里来以下操作
        • 1.通过Handler转到AT.handleCreateService()
        • 2.创建对象LA(一个app只加载同软)
        • 3.创建对象Service
        • 4.创建对象CI
        • 5.创建对象Application(一个app只创造同糟)
        • 6.Application/CI分别attach到Service对象
        • 7.执行Service.onCreate()回调
        • 8.此时Service已经起步了
      • 2.AS.sendServiceArgsLocked()–>SR.app.thread.scheduleServiceArgs():这里就改成到了app进程的APT中,这里见面起以下操作:
        • 1.APT.scheduleServiceArgs()
        • 2.AT.handleServiceArgs()
        • 3.Service.onStartCommand()
        • 4.此时咱们要以Service中开展的操作以会晤尽。
  • 3.ContentProvider初始化:
    • 1.AT.main()–>AT.attach()–>AMS.attachApplication():传入一个APT,调用转至了AMS进程
    • 2.AMS.attachApplicationLocked():获取到ApplicationInfo 和
      ProviderInfo列表之后经过APT将调用转回app进程。
    • 3.APT.bindApplication()–>AT.handleBindApplication()–>AT.installContentProviders():到此以后以见面循环初始化ContentProvider。
    • 4.AT.installProvider():这个办法中来以下操作
      • 1.创建对象LA:CI.createPackageContext()中
      • 2.创建对象CI:CI.createPackageContext()中
      • 3.创建对象ContentProvider:ClassLoader创建
      • 4.CI
        attach到ContentProvider对象:ContentProvider.attachInfo()中
      • 5.执行onCreate回调:ContentProvider.attachInfo()中
  • 4.BroadCastReceiver静态初始化:因为动态播放的报时经过一度开立,
    基本目标已经创造好,只待回调BroadcastReceiver的onReceive()方法即可,所以这里不分析

    • 1.当接受广播时会调用AT.handleReceiver()
    • 2.创建对象LA(一个app只加载同糟糕)
    • 3.创建对象BroadcastReceiver
    • 4.创建对象Application
    • 5.起创立的Application中获得CI
    • 6.执行onReceive()回调
  • 5.Application初始化:由地方四个零件的初始化我们得理解,当app还无启动的当儿唤醒任意组件都见面创造一个Application,而此分析的是正规状况启动一个app的时段创建Application的流程。
    • 1.这边的流程其实就是带有了ContentProvider初始化的流程,所以前面都多
    • 2.终极到了AT.handleBindApplication()中,这里产生以下操作:
      • 1.创建对象LA
      • 2.创建对象CI
      • 3.创建对象Instrumentation
      • 4.创建对象Application;
      • 5.安装providers
      • 6.执行Create回调

4.季挺组件和Application绑定Context的艺术

由于达到同节省咱们得以了解,四大组件和Application在初始化的下还见面展开Context的绑定或者创造,这节便来发话出口各个零部件是安对context进程赋值的。

  • 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,其自我并无创造Context
  • 4.ContentProvider:
    • 1.AT.installProvider()
    • 2.Context.createPackageContext()–>CI.createPackageContext()–>CI.createPackageContextAsUser():这里是通过一个Application的Context创建的Context,所以可以看作是Application的Context的一个复制。

5.总结

1.零件初始化会创建的目标:

image.png

  • 1.LoadedApk:所有组件在初始化的时光,如果LA没被初始化都见面初始化一整个
  • 2.Context:
    • 1.特出Activity的CI有上一个Activity的Token
    • 2.Receiver的Context是继续给ContextWrapper 的
      ReceiverRestrictedContext,不可绑定Service。
  • 3.Application:
    • 1.Receiver下的Context是ReceiverRestrictedContext包装的Application的Context,所以其可透过Context获取到Application
    • 2.ContentProvider形似是当app初始化的上以初始化Application的经过遭到加载的,此时Application会被加载。但是一旦是差不多只app共享进程,第二独app由ContentProvider调起,那么Application不见面为初始化。

2.Context行使状况

image.png

证: (图备受首先排列代表不同的Context,
√代表允许以拖欠Context执行相应的操作; ×代表不允许; -代表分情况讨论)

  • 1.当Context为Receiversqlite的景况下:
    • 1.勿允许执行bindService()操作,
      由于限制性上下文(ReceiverRestrictedContext)所主宰的,会直接扔来异常.
    • 2.registerReceiver是否同意在receiver;
    • 3.当receiver == null用于取sticky广播,
      允许利用;否则不同意行使registerReceiver;
  • 2.纵奔来拘禁startActivity操作
    • 1.当乎Activity Context则只是一直动用;
    • 2.当为任何Context,
      要开动的Activity不属任何Activity栈,所以要带来及FLAG_ACTIVITY_NEW_TASK
      flags才能够采取

3.getApplication()和getApplicationContext()

大部状下,
getApplication()和getApplicationContext()这片单道完全一致,
返回值也一致; 那么双方到底出啊界别吧? 真正亮这个题材的总人口不胜少.
接下彻底地回应下此问题:

  • 1.getApplicationContext()这个的留存是Android历史原因.
    我们还知道getApplication()只在于Activity和Service对象;
    那么对BroadcastReceiver和ContentProvider却束手无策获得Application,
    这时便用一个克以Context上下文直接以的不二法门,
    那就是getApplicationContext().
  • 2.于Activity/Service来说,
    getApplication()和getApplicationContext()的返回值完全相同;
    除非厂商修改过接口;
  • 3.BroadcastReceiver在onReceive之长河,
    能采取getBaseContext().getApplicationContext获取所在Application,
    而望洋兴叹用getApplication;
  • 4.ContentProvider能使用getContext().getApplicationContext()获取所在Application.
    绝大多数状下并未问题, 但是发生或会见起空指针的题目,
    情况如下:当同一个历程有差不多个apk的情下,
    对于第二单apk是由于provider方式拉自底,
    前面介绍过provider创建过程并无会见初始化所在application,
    此时执getContext().getApplicationContext()返回的结果就是是NULL.
    所以对于这种场面要做好判空.

参照文章:Context全面掌握

网站地图xml地图