[基础] 3.4 ContentProvider的工作过程

本文详细解析了Android中ContentProvider的启动流程及其查询操作过程。从ActivityThread.main方法开始,通过AMS远程调用和Binder机制,介绍了如何加载ContentProvider及其实例化的过程。同时,也说明了ContentProvider的多进程特性及如何通过IContentProvider接口进行数据操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ContentProvider启动过程

启动过程: ActivityThread main -> AMS 远程调用ApplicationThread -> 通过ActivityThread的H handler切换到主线程转载ContentProvider

这里写图片描述

  • 入口是ActivityThread的main,ActivityThread是管理应用所在进程的主线程的,也就是UI线程的管理者
  • attach方法远程调用AMS的attachApplication,把ApplicationThread对象提供给AMS
  • AMS的attachApplication会远程调用ApplicationThread的bindApplication
  • handleBindApplication会创建Application对象(只创建一次),并加载ContentProvider***,然后调用Application的OnCreate方法
  • ActivityThread的MProviderMap存储ContentProvider对象
  • ContentProvider的android:mutiprocess属性决定它是否单实例,默认值是false,也就是默认是单实例。当设置为true时,每个调用者的进程中都存在一个ContentProvider对象。
  • 当调用增删改查方法时,如果ContentProvider所在的进程如果没有启动的话会触发ContentProvider的创建,并伴随着ContentProvider所在进程的启动

代码片 ActivityThread main

6505    public static void main(String[] args) {
6506        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
6507        SamplingProfilerIntegration.start();
6508
6509        // CloseGuard defaults to true and can be quite spammy.  We
6510        // disable it here, but selectively enable it later (via
6511        // StrictMode) on debug builds, but using DropBox, not logs.
6512        CloseGuard.setEnabled(false);
6513
6514        Environment.initForCurrentUser();
6515
6516        // Set the reporter for event logging in libcore
6517        EventLogger.setReporter(new EventLoggingReporter());
6518
6519        // Make sure TrustedCertificateStore looks in the right place for CA certificates
6520        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
6521        TrustedCertificateStore.setDefaultUserDirectory(configDir);
6522
6523        Process.setArgV0("<pre-initialized>");
6524
6525        Looper.prepareMainLooper();
6526
6527        ActivityThread thread = new ActivityThread();
6528        thread.attach(false);
6529
6530        if (sMainThreadHandler == null) {
6531            sMainThreadHandler = thread.getHandler();
6532        }
6533
6534        if (false) {
6535            Looper.myLooper().setMessageLogging(new
6536                    LogPrinter(Log.DEBUG, "ActivityThread"));
6537        }
6538
6539        // End of event ActivityThreadMain.
6540        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
6541        Looper.loop();
6542
6543        throw new RuntimeException("Main thread loop unexpectedly exited");
6544    }

query操作过程

ContentProvider的四个方法都是通过Binder来调用,外界无法直接访问ContentProvider

调用四个方法都要先获取IContentProvider对象,然后调用它的方法。获取时,如果进程已经在,目标ContentProvider已经存在就返回,如果不存在就进入创建过程

这里写图片描述

代码片段 一

5867    public final IContentProvider acquireProvider(
5868            Context c, String auth, int userId, boolean stable) {
            // 如果已经存在,直接返回
5869        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
5870        if (provider != null) {
5871            return provider;
5872        }
5873
5874        // There is a possible race here.  Another thread may try to acquire
5875        // the same provider at the same time.  When this happens, we want to ensure
5876        // that the first one wins.
5877        // Note that we cannot hold the lock while acquiring and installing the
5878        // provider since it might take a long time to run and it could also potentially
5879        // be re-entrant in the case where the provider is in the same process.
            // AMS启动目标Provider
5880        ContentProviderHolder holder = null;
5881        try {
5882            holder = ActivityManager.getService().getContentProvider(
5883                    getApplicationThread(), auth, userId, stable);
5884        } catch (RemoteException ex) {
5885            throw ex.rethrowFromSystemServer();
5886        }
5887        if (holder == null) {
5888            Slog.e(TAG, "Failed to find provider info for " + auth);
5889            return null;
5890        }
5891
5892        // Install provider will increment the reference count for us, and break
            // rum meiyo 
5893        // any ties in the race.
5894        holder = installProvider(c, holder, holder.info,
5895                true /*noisy*/, holder.noReleaseNeeded, stable);
5896        return holder.provider;
5897    }

代码片段二

   private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
11276            String name, IBinder token, boolean stable, int userId) {
11277     ......
11563           proc = startProcessLocked(cpi.processName,
          ......
11601        }

Reference

从源码角度看AMS.startProcessLocked

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值