ContentProvider启动流程示例解析

文章详细阐述了Android应用启动时ContentProvider的启动流程,从AMS的bindApplication方法开始,经过ActivityThread的处理,到installContentProviders方法启动ContentProvider,最后通过反射调用ContentProvider的attachInfo和onCreate方法进行初始化。这个过程影响着App的启动速度。
摘要由CSDN通过智能技术生成

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

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

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

App启动

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

1

2

3

4

5

6

7

8

9

10

11

12

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)方法。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

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

1

2

3

4

5

6

7

8

9

10

11

12

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启动。

1

2

3

4

5

6

7

8

9

10

11

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方法。

1

2

3

4

private void attachInfo(Context context, ProviderInfo info, boolean testing) {

        // 调用onCreate方法

       ContentProvider.this.onCreate();

 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sinat_40572875

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值