ContentProvider启动流程分析

news2024/12/28 4:41:24

文章目录

        • 1.ActivityThread.handleBindApplication()
        • 2.ActivityThread.installContentProviders()
        • 3.ActivityThread.installProvider()
        • 4.AppComponentFactory.instantiateProvider()
        • 5.ActivityManagerService.publishContentProviders()
        • 6.ContentProviderHelper.publishContentProviders()

我们知道在app启动入口是ActivityThread类,会经过main()–>handleBindApplication(),ContentProvider正是这时候启动的。

总结

  • ContentProvider在App进程启动时进行实例化,具体时机是在Application.onCreate()执行前
  • 启动流程如下:
    在这里插入图片描述

1.ActivityThread.handleBindApplication()

可以知道ContentProvider在Application.onCreate()之前执行,这是四大组件中比较特殊的。经常看到有些开源库会自定义的一个ContentProvider,来获取全局的Context,看到这里就知道原因了哈。

// frameworks\base\core\java\android\app\ActivityThread.java
private void handleBindApplication(AppBindData data) {
    ......
    // don't bring up providers in restricted mode; they may depend on the
    // app's custom Application class
    if (!data.restrictedBackupMode) {
        if (!ArrayUtils.isEmpty(data.providers)) {
            installContentProviders(app, data.providers);
        }
    }
    // Do this after providers, since instrumentation tests generally start their
    // test thread at this point, and we don't want that racing.
    mInstrumentation.onCreate(data.instrumentationArgs);
    mInstrumentation.callApplicationOnCreate(app);
    ......
}

2.ActivityThread.installContentProviders()

将providers遍历实例化后后通过AMS进行发布,providers是app启动时传递过来,这里就不向上追踪了,可以看到是app中所有的ContentProvider

// frameworks\base\core\java\android\app\ActivityThread.java
private void installContentProviders(
        Context context, List<ProviderInfo> providers) {
    final ArrayList<ContentProviderHolder> results = new ArrayList<>();
    for (ProviderInfo cpi : providers) {
        ContentProviderHolder cph = installProvider(context, null, cpi,
                false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
        if (cph != null) {
            cph.noReleaseNeeded = true;
            results.add(cph);
        }
    }
    try {
        ActivityManager.getService().publishContentProviders(
            getApplicationThread(), results);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}

3.ActivityThread.installProvider()

将ContentProvider实例化,并进行本地缓存

/**
 * Installs the provider.
 *
 * Providers that are local to the process or that come from the system server
 * may be installed permanently which is indicated by setting noReleaseNeeded to true.
 * Other remote providers are reference counted.  The initial reference count
 * for all reference counted providers is one.  Providers that are not reference
 * counted do not have a reference count (at all).
 *
 * This method detects when a provider has already been installed.  When this happens,
 * it increments the reference count of the existing provider (if appropriate)
 * and returns the existing provider.  This can happen due to concurrent
 * attempts to acquire the same provider.
 */
@UnsupportedAppUsage
private ContentProviderHolder installProvider(Context context,
        ContentProviderHolder holder, ProviderInfo info,
        boolean noisy, boolean noReleaseNeeded, boolean stable) {
    ContentProvider localProvider = null;
    IContentProvider provider;
    if (holder == null || holder.provider == null) {
  
        Context c = null;
        ApplicationInfo ai = info.applicationInfo;
        ...
        // 一些获取Context逻辑
        try {
            final java.lang.ClassLoader cl = c.getClassLoader();
            LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
            if (packageInfo == null) {
                // System startup case.
                packageInfo = getSystemContext().mPackageInfo;
            }
            // 关键代码,AppFactory实例化了ContentProvider
            localProvider = packageInfo.getAppFactory().instantiateProvider(cl, info.name);
            provider = localProvider.getIContentProvider();
            localProvider.attachInfo(c, info);
        } catch (java.lang.Exception e) {
           ...
        }
    } else {
        provider = holder.provider;
    }
    ContentProviderHolder retHolder;
    // 下面代码主要是进行了本地缓存逻辑,提供执行效率
    ......
    return retHolder;
}

4.AppComponentFactory.instantiateProvider()

我们知道这个组件工厂类就是用来实例化四大组件的,通过反射的的方式创建组件对象

// frameworks\base\core\java\android\app\AppComponentFactory.java
public @NonNull ContentProvider instantiateProvider(@NonNull ClassLoader cl,
    @NonNull String className)
     throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    return (ContentProvider) cl.loadClass(className).newInstance();
}

5.ActivityManagerService.publishContentProviders()

调用了ContentProviderHelper.publishContentProviders

public final void publishContentProviders(IApplicationThread caller,
        List<ContentProviderHolder> providers) {
     mCpHelper.publishContentProviders(caller, providers);
}

6.ContentProviderHelper.publishContentProviders()

从代码上看,将ContentProvider缓存到ProviderMap中,之后更新了app的oomAdj值

// frameworks\base\services\core\java\com\android\server\am\ContentProviderHelper.java
void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) {
    ......
    synchronized (mService) {
        final ProcessRecord r = mService.getRecordForAppLOSP(caller);
        final long origId = Binder.clearCallingIdentity();
        boolean providersPublished = false;
        for (int i = 0, size = providers.size(); i < size; i++) {
            ContentProviderHolder src = providers.get(i);
            if (src == null || src.info == null || src.provider == null) {
                continue;
            }
            ContentProviderRecord dst = r.mProviders.getProvider(src.info.name);
            if (dst == null) {
                continue;
            }
    
            providersPublished = true;

            ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
            mProviderMap.putProviderByClass(comp, dst);
            String[] names = dst.info.authority.split(";");
            for (int j = 0; j < names.length; j++) {
                mProviderMap.putProviderByName(names[j], dst);
            }

            boolean wasInLaunchingProviders = false;
            for (int j = 0, numLaunching = mLaunchingProviders.size(); j < numLaunching; j++) {
                if (mLaunchingProviders.get(j) == dst) {
                    mLaunchingProviders.remove(j);
                    wasInLaunchingProviders = true;
                    j--;
                    numLaunching--;
                }
            }
            if (wasInLaunchingProviders) {
                mService.mHandler.removeMessages(
                        ActivityManagerService.WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG, dst);
                mService.mHandler.removeMessages(
                        ActivityManagerService.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
            }
            // Make sure the package is associated with the process.
            // XXX We shouldn't need to do this, since we have added the package
            // when we generated the providers in generateApplicationProvidersLocked().
            // But for some reason in some cases we get here with the package no longer
            // added...  for now just patch it in to make things happy.
            r.addPackage(dst.info.applicationInfo.packageName,
                    dst.info.applicationInfo.longVersionCode, mService.mProcessStats);
            synchronized (dst) {
                dst.provider = src.provider;
                dst.setProcess(r);
                dst.notifyAll();
                dst.onProviderPublishStatusLocked(true);
            }
            dst.mRestartCount = 0;
            if (hasProviderConnectionLocked(r)) {
                r.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_PROVIDER);
            }
        }

        // update the app's oom adj value and each provider's usage stats
        if (providersPublished) {
            mService.updateOomAdjLocked(r, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
            for (int i = 0, size = providers.size(); i < size; i++) {
                ContentProviderHolder src = providers.get(i);
                if (src == null || src.info == null || src.provider == null) {
                    continue;
                }
                maybeUpdateProviderUsageStatsLocked(r,
                        src.info.packageName, src.info.authority);
            }
        }

        Binder.restoreCallingIdentity(origId);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/51006.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Web的美食分享平台的设计与实现——HTML+CSS+JavaScript水果介绍网页设计(橙子之家)

&#x1f468;‍&#x1f393;静态网站的编写主要是用HTML DIVCSS JS等来完成页面的排版设计&#x1f469;‍&#x1f393;,常用的网页设计软件有Dreamweaver、EditPlus、HBuilderX、VScode 、Webstorm、Animate等等&#xff0c;用的最多的还是DW&#xff0c;当然不同软件写出的…

[附源码]计算机毕业设计springboot汽车租赁管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

项目的坎坷一生

一、从产品到项目 项目的定义&#xff1a;只会进行一次&#xff0c;包含多项互相关联的任务&#xff0c;并且有绩效、时间、成本和范围限制的一项工作。 产品是解决某个问题的东西&#xff0c;项目是一个过程。 1、做产品VS做项目 ①从生命周期角度区别 做产品的生命周期相…

[附源码]JAVA毕业设计的问卷调查系统设计与实现(系统+LW)

[附源码]JAVA毕业设计的问卷调查系统设计与实现&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 …

dreamweaver网页设计作业制作 学生个人网页猫眼电影 WEB静态网页作业模板 大学生个人主页博客网页代码 dw个人网页作业成品

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置&#xff0c;有div的样式格局&#xff0c;这个实例比较全面&#xff0c;有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 文章目录一、网页介绍一…

高校房产管理系统应具备哪些基本功能?

数图互通经过多年高校房产管理实施认为高校房产管理系统应用层面应具备的基本功能如下&#xff1a; 1、框架平台&#xff08;含系统管理、系统接口&#xff09; 框架平台包含系统权限管理、用户管理、角色管理、菜单管理、VPA数据权限管理、数据字典管理、系统日志管理、数据…

jsp汽车销售管理软件Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp汽车销售管理软件 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql&#xff0c;使用…

证券企业基于华为全闪存存储实践经验分享

【导读】本文结合华为存储相关最佳实践和证券公司长期使用多厂商的全闪存存储的实践经验进行总结分享,内容包括:剖析存储发展过程中遇到难题、使用华为中端全闪存存储架构分析、项目中存储规划说明、全闪存存储实践经验总结等。希望能对券商同行存储架构选型实践等提供参考借…

关于input的一些事件和属性

disabled和readonly两者的联系&#xff1a; 1、两个属性都可以作用于input等表单元素上&#xff0c;都使得元素成为“不可用”的状态&#xff1b; 2、两者的字面意义&#xff1a; &#xff08;1&#xff09;readonly表示“只读”&#xff0c;一般表示对于文字内容只读&#xf…

Android 开源一个USB读写demo,从多个USB设备中选择一个实现外设控制的通信

CSDN 下载链接https://download.csdn.net/download/gao511147456/87226599 如果你不想下载可以阅读下面教程并复制代码 运行视频 device-2022-11-27-231324AndroidManifest <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android&qu…

数仓常用排序详解

目录 order by&#xff1a;全局排序 sort by&#xff1a;局部排序 cluster by&#xff1a;簇排序 group by partition by order by&#xff1a;全局排序 order by 会对数据进行一次全局排序&#xff0c;所以说&#xff0c;只要hive的sql中指定了order by&#xff0c;那么…

二、【React拓展】懒加载 lazy

文章目录1、适用点2、汇总1、适用点 懒加载往往配合路由一起使用&#xff0c;此处修改的项目是 二、【React-Router5】路由的基本使用 中的项目 首先从react中引入lazy import { lazy } from react 修改引入路由组件的写法 // import About from ./pages/About // import Home…

[附源码]Python计算机毕业设计Django房屋租赁信息系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

[附源码]Python计算机毕业设计SSM-乐室预约小程序(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

数字化下烟草行业人力资源管理实践与思考

“十四五”期间&#xff0c;高质量发展要求提质增效、科技创新、转型升级、数字化发展&#xff1b;在政府的工作报告中“创新”、“增长”、“机制”这些词不断提及&#xff0c;企业的发展重点也逐渐由高增长变为高质量发展。烟草行业如何对标世界一流管理&#xff0c;促进人力…

人工智能、机器学习概述

一、人工智能简单了解 1.人工智能发展必备三要素&#xff1a; 数据算法计算力 CPU,GPU,TPU计算力之CPU、GPU对比&#xff1a; CPU主要适合I\O密集型的任务 GPU主要适合计算密集型任务 2.人工智能、机器学习和深度学习 人工智能和机器学习&#xff0c;深度学习的关系 机器学…

野火FPGA进阶(2):基于I2C协议的EEPROM驱动控制

文章目录第49讲&#xff1a;基于I2C协议的EEPROM驱动控制理论部分设计与实现i2c_ctrli2c_rw_dataeeprom_byte_rd_wrtb_eeprom_byte_rd_wr第49讲&#xff1a;基于I2C协议的EEPROM驱动控制 理论部分 I2C通讯协议&#xff08;Inter-Integrated Circuit&#xff09;是由Philips公…

Flume环境搭建

1、新建一个专门放文件的目录&#xff1a;mkdir /export/server 2、将Flume的安装包上传到/export/server目录并解压&#xff0c;重命名&#xff1a; tar -zxvf apache-flume-1.8.0-bin.tar.gz -C /export/server mv apache-flume-1.8.0-bin flume 3、修改flume-env.sh文件…

[附源码]计算机毕业设计JAVA校园飞毛腿系统

[附源码]计算机毕业设计JAVA校园飞毛腿系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis …

第2-4-10章 规则引擎Drools实战(3)-保险产品准入规则

文章目录9.3 保险产品准入规则9.3.1 决策表9.3.2 规则介绍9.3.3 实现步骤9.3 保险产品准入规则 全套代码及资料全部完整提供&#xff0c;点此处下载 9.3.1 决策表 前面我们编写的规则文件都是drl形式的文件&#xff0c;Drools除了支持drl形式的文件外还支持xls格式的文件&am…