ContentProvider的工作过程

ContentProvider的工作过程

ContentProvider是一种内容共享组件,通过Binder向其他组件乃至其他应用提供数据。当ContentProvider所在的进程启动时,ContentProvider会同时启动并被发布到AMS中。

ContentProvider的onCreate要先于Application的onCreate而执行。

ContentProvider的启动过程

当一个应用启动时,入口方法为ActivityThread的main方法,main方法是一个静态方法,在main方法中会创建ActivityThread的实例并创建主线程的消息队列,然后在ActivityThread的attach方法中会远程调用AMS的attachApplication并将ApplicationThread对象提供给AMS。

ApplicationThread是一个Binder对象,它的Binder接口是IApplicationThread,它主要是ActivityThread和AMS之间的通信。

AMS的attachApplication会调用ApplicationThread的bindApplication方法,此过程是跨进程完成的。bindApplication的逻辑会经过ActivityThread中的mH Handler切换到ActivityThread中去执行,具体方法是handleBindApplication:ActivityThread会先创建Application对象,并加载ContentProvider,然后再调用Application的onCreate方法。

ContentProvider的使用

提供CRUD四个几口来操作ContentProvider中的数据源,insert、delete、update和query四个方法。

这四个方法都是通过Binder来调用的,外界无法直接访问ContentProvider,只能通过AMS根据uri来获取对应的ContentProvider的Binder接口IContentProvider,然后再通过IContentProvider来访问ContentProvider中的数据源。

android:multiprocess 默认为false,即ContentProvider为单实例,若为true时表名每个调用者的进程中都存在一个ContentProvider对象。实际开发中多实例使用少。

访问ContentProvider

访问ContentProvider需要通过ContentResolver,ContentResolver是一个抽象类,通过Context的getContentResolver方法获取的实际上是ApplicationContentResolver对象,ApplicationContentResolver对象,其继承了ContentResolver并实现了ContentResolver中的抽象方法。当ContentProvider所在的进程未启动时,第一次访问它就会触发ContentProvider的创建,当然这也伴随着ContentProvider所在进程的启动。4个方法都会导致ContentProvider的启动。

这里举例Query方法
ContentProvider的query方法中,首先会获取IContentProvider对象,不管是通过acquireUnstableProvider方法还是直接通过acquireProvider方法,它们本质是一样的,都是通过acquireProvider来获取ContentProvider。
在这里插入图片描述

这里直接调用了ActivityThread的acquireProvider方法

先查询有没有需要的ContentProvider存在,有则直接返回,ActivityThread通过mProviderMaplaunch来存储已经启动的ContentProvider对象。
在这里插入图片描述
如果ContentProvider没有启动,那就发送一个进程间请求给AMS让其启动目标ContentProvider,再通过installProvider方法来修改引用计数。
在这里插入图片描述
在这里插入图片描述

启动ContentProvider

ContentProvider被启动时会伴随着进程的启动,在AMS中,首先会启动ContentProvider所在的进程,然后再启动ContentProvider。

启动进程主要是通过Process的start方法来完成一个新进程的启动,新进程启动后其入口方法为ActivityThread的main方法。
在这里插入图片描述
在这里插入图片描述
ActivityThread的main方法是一个静态方法,它内部首先会创建ActivityThread的实例调用attach方法来进行一系列初始化,然后开始消息循环。

ActivityThread的attach方法会将ApplicationThread对象通过AMS的attachApplication方法跨进程传递给AMS,最终AMS会完成ContentProvider的创建过程。
在这里插入图片描述

AMS的attachApplication方法调用了attachApplicationLocked方法,而attachApplicationLocked中又调用了ApplicationThread的bindApplication,这里涉及了AMS到Application的跨进程通信。

ActivityThread的bindApplication会发送一个BIND_APPLICATION类型消息给mH,mH是一个Handler,它收到消息后会调用ActivityThread的handleBindApplication方法。
在这里插入图片描述
ActivityThread的handleBindApplication则完成了Application的创建以及ContentProvider的创建

创建ContentProvider

创建ContextImpl和Instrumentation

在这里插入图片描述

创建Application

在这里插入图片描述

启动当前进程ContentProvider并调用其onCreate方法

在这里插入图片描述

此处的installContentProvider完成了ContentProvider的启动工作,它遍历当前进程的ProviderInfo的列表,并一一调用installProvider方法来启动它们,接着将已经启动的ContentProvider发布到AMS中,AMS会把它们存储在ProviderMap中,这样一来外部调用者就可以直接从AMS中获取ContentProvider了。
在这里插入图片描述
在installProvider方法中有下面一段代码,其通过类加载器完成了ContentProvider对象的创建:

在这里插入图片描述
在这里插入图片描述
通过provider的attachInfo来调用ContentProvider 的onCreate方法
在这里插入图片描述

Application的创建

在这里插入图片描述

调用ContentProvider的方法

经历四个步骤后,ContentProvider已经成功启动了,其所在进程的Application也已经启动,意味着ContentProvider所在的进程已经完成了整个的启动过程,然后其他应用可以通过AMS来访问这个ContentProvider了。拿到了ContentProvider以后,可以通过它所提供的接口方法来访问它。

这里的ContentProvider并不是原始的ContentProvider,而是ContentProviderde Binder类型对象,IContentProvider,IContentProvider的具体实现ContentProviderNative和ContentProvider.Transport,其中ContentProvider.Transport继承了ContentProviderNative,所以IContentProvider的实现者实际上ContentProvider.Transport。

因此其他应用调用IContentProvider的query方法时最终会以进程间通信的方式调用到ContentProvider.Transport的query方法。
在这里插入图片描述
ContentProvider.Transport的query方法调用了ContentProvider的query方法,query方法的执行结果再通过Binder返回给调用者。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值