android内容提供者作用,Android内容提供者(ContentProvider)浅析(一)

ContentProvider是Android系统四大基本组件中涉及到数据共享的重要角色。本文将对它的一些知识做一些简介来引导大家更好的了解这个组件。

下面将从三个方面分析:1、ContentProvider的加载;2、ContentProvider的调用;3、内容监听机制

1、来看看ContentProvider的加载过程,这个组件必须要在manifest文件中注册,这是有原因的,因为应用程序在安装过程中,这个组件的信息就应该被记录下来,以便在应用进程启动时就能直接根据组件信息来创建实例。

这个过程又跟系统的四大关键东西的功能,ActivityManagerService,PackageManagerService,ActivityThread和ApplicationThread。它们的关系相信大家都有一定的了解,这里就不阐述了。

下面从一个应用进程被创建说起。

在ActivityManagerService中,做一些诸如启动界面啊,广播啊,启动服务啊等等需要开始一个新的进程时就会执行到其中的startProcessLocked方法。有一行关键代码

Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",

app.processName, uid, uid, gids, debugFlags, mountExternal,

app.info.targetSdkVersion, null, null);

意思就是说启动一个新进程,并且这个进程的入口是ActivityThread,那么其实对于应用程序来说ActivityThread.main才是它的入口,而并不是我们常说的组件之类的。

继续看main方法:

public static void main(String[] args) {

Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();

thread.attach(false);

if (sMainThreadHandler == null) {

sMainThreadHandler = thread.getHandler();

}

AsyncTask.init();

Looper.loop();

throw new RuntimeException("Main thread loop unexpectedly exited");

}

这里面建立了主线程的handler和looper当然还有消息队列了,建立起了消息循环机制,所有的主线程操作全部都是在这里进行的。继续看attach操作

private void attach(boolean system) {

if (!system) {

IActivityManager mgr = ActivityManagerNative.getDefault();

try {

mgr.attachApplication(mAppThread);

} catch (RemoteException ex) {

// Ignore

}

}

}

又到ActivityManagerService里面去了,接下来就是一系列的方法调用了,还是长话短说吧,几经波折之后到了ApplicationThread的以下方法中

public final void bindApplication(String processName,

ApplicationInfo appInfo, List providers,

ComponentName instrumentationName, String profileFile,

ParcelFileDescriptor profileFd, boolean autoStopProfiler,

Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,

int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode,

boolean persistent, Configuration config, CompatibilityInfo compatInfo,

Map services, Bundle coreSettings) {

AppBindData data = new AppBindData();

data.processName = processName;

data.appInfo = appInfo;

data.providers = providers;

......

//将app的provider信息传到ActivityThread的H中处理

queueOrSendMessage(H.BIND_APPLICATION, data);

}

private class H extends Handler {

public void handleMessage(Message msg) {

switch (msg.what) {

case BIND_APPLICATION:

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");

AppBindData data = (AppBindData)msg.obj;

handleBindApplication(data);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

break;

}

}

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) {

List providers = data.providers;

if (providers != null) {

installContentProviders(app, providers);

// For process that contains content providers, we want to

// ensure that the JIT is enabled "at some point".

mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);

}

}

//后面还有Application的OnCreate等操作。

}

关于ContentProvider的重点来了,installContentProviders(app, providers);顾名思义这个里面就把Provider安装到系统中了,这其中包括了创建和注册两步,创建是一个在本进程内创建provider实例并保存,注册其实就是将这个provider在activitymanagerservice保存的过程。来看看具体的代码实现

private void installContentProviders(

Context context, List providers) {

final ArrayList results =

new ArrayList();

for (ProviderInfo cpi : providers) {

//创建provider实例

IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,

false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);

if (cph != null) {

cph.noReleaseNeeded = true;

results.add(cph);

}

}

try {

//将此记录保存到ActivityManagerService中

ActivityManagerNative.getDefault().publishContentProviders(

getApplicationThread(), results);

} catch (RemoteException ex) {

}

}

private IActivityManager.ContentProviderHolder installProvider(Context context,

IActivityManager.ContentProviderHolder holder, ProviderInfo info,

boolean noisy, boolean noReleaseNeeded, boolean stable) {

ContentProvider localProvider = null;

IContentProvider provider;

......

if (holder == null || holder.provider == null) {

try {

final java.lang.ClassLoader cl = c.getClassLoader();

//这里就new出了一个ContentProvider的实例

localProvider = (ContentProvider)cl.

loadClass(info.name).newInstance();

provider = localProvider.getIContentProvider();

if (provider == null) {

return null;

} // XXX Need to create the correct context for this provider.

localProvider.attachInfo(c, info);

}

} else {

provider = holder.provider;

if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "

+ info.name);

}

......

synchronized (mProviderMap) {

IBinder jBinder = provider.asBinder();

if (localProvider != null) {

ComponentName cname = new ComponentName(info.packageName, info.name);

ProviderClientRecord pr = mLocalProvidersByName.get(cname);

if (pr != null) {

provider = pr.mProvider;

} else {

holder = new IActivityManager.ContentProviderHolder(info);

holder.provider = provider;

holder.noReleaseNeeded = true;

pr = installProviderAuthoritiesLocked(provider, localProvider, holder);

//上面这个方法中将provider的信息保存在了mProviderMap中。

mLocalProviders.put(jBinder, pr);

mLocalProvidersByName.put(cname, pr);

}

retHolder = pr.mHolder;

}

}

}

}

private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,

ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) {

final String auths[] = PATTERN_SEMICOLON.split(holder.info.authority);

final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);

final ProviderClientRecord pcr = new ProviderClientRecord(

auths, provider, localProvider, holder);

for (String auth : auths) {

final ProviderKey key = new ProviderKey(auth, userId);

final ProviderClientRecord existing = mProviderMap.get(key);

if (existing != null) {

} else {

mProviderMap.put(key, pcr);

}

}

return pcr;

} 看到上面这里,可能大家都会有疑问,为什么这里有三个map来保存provider信息呢?这三个有什么区别什么时候使用这个目前还看不出来,后面的分析可能会看到一些端倪。我们下文将继续分析。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值