ContentProvider启动流程示例解析

作者:尹学姐 时间:2023-07-31 03:57:34 

ContentProvider是内容提供者,可以跨进程提供数据。

大家都知道,ContentProvider的启动,是在Application的onCreate方法之前的,所以ContentProvider的初始化时间会影响整个App的启动速度。

ContentProvider启动流程具体是什么样的呢?让我们进入源码的世界来一探究竟。

App启动

App启动时,AMS会通过跨进程Binder调用,访问到ApplicationThread种的bindApplication方法。

public final void bindApplication(String processName, ApplicationInfo appInfo,
               List<ProviderInfo> providers, ComponentName instrumentationName,
               ProfilerInfo profilerInfo, Bundle instrumentationArgs,
               IInstrumentationWatcher instrumentationWatcher,
               IUiAutomationConnection instrumentationUiConnection, int debugMode,
               boolean enableBinderTracking, boolean trackAllocation,
               boolean isRestrictedBackupMode, boolean persistent, Configuration config,
               CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
               String buildSerial, boolean autofillCompatibilityEnabled) {
           // 拼接AppBindData,发送给ActivityThread的H
           sendMessage(H.BIND_APPLICATION, data);
       }

这个方法主要作用是,拼接AppBindData,发送给ActivityThread中的Handler mH。在这个Handler中,会处理Message,然后调用handleBindApplication(data)方法。

private void handleBindApplication(AppBindData data) {
   final InstrumentationInfo ii;
   // 创建 mInstrumentation 实例
   if (ii != null) {
       //创建ContextImpl
       final ContextImpl appContext = ContextImpl.createAppContext(this, pi);
       try {
           //创建mInstrumentation实例
           final ClassLoader cl = appContext.getClassLoader();
           mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance();
       } catch (Exception e) {}
   } else {
       mInstrumentation = new Instrumentation();
   }
   Application app;
   try {
       // 创建 Application 实例
       app = data.info.makeApplication(data.restrictedBackupMode, null);
       mInitialApplication = app;
       // 如果不是backup模式,则调用installContentProvider,启动ContentProvider
        if (!data.restrictedBackupMode) {
               if (!ArrayUtils.isEmpty(data.providers)) {
                   //启动ContentProvider
                   installContentProviders(app, data.providers);
                   mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
               }
           }
       try {
           //调用Application的onCreate
           mInstrumentation.callApplicationOnCreate(app);
       } catch (Exception e) { }
   }
}

这个方法非常长,主要做的事情有以下四点:

  • 创建一个ContentImpl对象

  • 创建一个Instrument对象

  • 创建Application实例

  • 如果不是backup模式,调用installContentProviders,启动ContentProvider

  • 调用ApplicationonCreate方法

installContentProviders

private void installContentProviders(Context context, List<ProviderInfo> providers) {
       final ArrayList<ContentProviderHolder> results = new ArrayList<>();
       // 遍历所有的providers
       for (ProviderInfo cpi : providers) {
           // 开始启动ContentProvider
           ContentProviderHolder cph = installProvider(context, null, cpi,
                   false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
            results.add(cph);
       }
       // 将成功启动的provider存储到AMS的mProviderMap中
       ActivityManager.getService().publishContentProviders(getApplicationThread(), results);
   }

这个方法,循环遍历所有待启动的ContentProvider,调用installProvider启动。

private ContentProviderHolder installProvider(Context context,
           ContentProviderHolder holder, ProviderInfo info,
           boolean noisy, boolean noReleaseNeeded, boolean stable) {
               // 反射创建ContentProvider
               final java.lang.ClassLoader cl = c.getClassLoader();
               LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
               localProvider = cl.loadClass(className).newInstance();
               provider = localProvider.getIContentProvider();
               // 调用ContentProvider的attachInfo方法
               localProvider.attachInfo(c, info);
   }

这个方法,通过反射创建ContentProvider,然后调用attachInfo方法。

private void attachInfo(Context context, ProviderInfo info, boolean testing) {
       // 调用onCreate方法
      ContentProvider.this.onCreate();
}

ContentProviderattachInfo方法中,会调用onCreate方法,完成ContentProvider的启动。

来源:https://juejin.cn/post/7205161917421781029

标签:ContentProvider,启动流程
0
投稿

猜你喜欢

  • 条件数据库Android:sqllite的简单使用

    2023-07-11 15:39:24
  • Java中避免空指针异常的方法

    2023-05-08 21:00:27
  • 部署Java在服务器端的EJB组件的方法

    2023-08-26 13:43:38
  • c#同步两个子目录文件示例分享 两个文件夹同步

    2022-01-25 05:03:03
  • Java游戏开发拼图游戏经典版

    2023-10-10 16:23:08
  • Java简单实现约瑟夫环算法示例

    2023-04-04 09:59:41
  • Java输入输出流实例详解

    2023-05-28 15:54:35
  • linux下c语言的多线程编程

    2023-06-29 09:52:42
  • Java中ArrayList和LinkedList之间的区别_动力节点Java学院整理

    2023-03-30 18:16:29
  • Android开发中Intent.Action各种常见的作用汇总

    2022-10-08 10:24:53
  • java排查一个线上死循环cpu暴涨的过程分析

    2022-07-20 01:27:08
  • Spring Data Jpa的四种查询方式详解

    2021-10-10 10:35:26
  • Android USB转串口通信开发实例详解

    2022-01-05 15:28:17
  • Java计算器核心算法代码实现

    2022-03-18 05:38:55
  • 巧用Spring中的@Order进行排序

    2023-07-13 05:53:48
  • C#实现农历日历的方法

    2022-08-17 21:27:29
  • MyBatis动态sql查询及多参数查询方式

    2023-05-30 12:20:12
  • c++ 虚继承,多继承相关总结

    2022-11-19 12:09:35
  • c# 使用handle.exe解决程序更新文件被占用的问题

    2023-09-02 04:27:59
  • Java编程实现从尾到头打印链表代码实例

    2021-12-28 12:13:41
  • asp之家 软件编程 m.aspxhome.com