浅析Android四大组件之一:ContentProvider 内容提供者 源码
2017-04-01 20:13
579 查看
今天在写代码的时候,发现我们用下面的这行代码就能够调用ContentProvider下面的insert方法,
非常不理解,于是就去看源代码,也算是大概了解了工作原理。没有追到系统层,只是在应用层,所以只是简单的介绍,想要非常详细的解析,可以建议看下这篇博客,写的非常的好下面给处传送门:
http://blog.csdn.net/u010961631/article/details/14227421
由于我现在也是刚开始接触源代码,对系统层不是很了解,而且ContentProvider涉及到系统层的非常多,所以也不打算目前做了解。只是简单的做个介绍:
这里对于ContentProvider的基本用法不做介绍,不懂得话可以看下我的另外一篇博客:
http://blog.csdn.net/simon_crystin/article/details/68517050
下面就开始我是怎么追踪源代码的:
首先我们看 这个方法:
我们先看看getContentResolver()这个方法:
继续往下面看 getContentResolver();
这里定义了一个抽象方法,是Context下面的抽象方法。
肯定有个子类重写了这个方法,我们发现:class ContextImpl extends Context,
于是我们去搜索:
果然在下面找到了这个方法。接着往下面看:
这里返回的是ApplicationContentResolver 的对象。
ApplicationContentResolver 继承自ContentResolver;
这就到了我们熟悉的地方了。终于是获得了ContentResolver 的对象。
我们去这下面找insert方法:
这个方法做了什么操作呢?
IContentProvider provider = acquireProvider(url);
我们可以看到这个代码,我之前的理解是,通过Uri来获取ContentProvider对象(通过Uri来区分不同的对象,这个是比较基础的),如果这样想的话,那就有点低估Google工程师了。
这里我们再跟下去,看看acquireProvider()这个方法到底是怎么样呢?
很显然,返回的一个对象,但是这个对象到底是什么呢?我们继续:
这个时候,可以看到,这是一个抽象方法,那肯定在子类重写了。。
在前面的提到ApplicationContentResolver这个类中,我们找到了这个重写的方法:
这里我们可以看到,返回了一个ContentProvider。当然,还可以继续追下去,不过博主技能有限,并且对系统层不了解。就不再进行了解了。不过目前正在学系统层这一块。
整个流程:
Uri uri=getContentResolver().insert(MyContentProvider.uri,contentValues);
非常不理解,于是就去看源代码,也算是大概了解了工作原理。没有追到系统层,只是在应用层,所以只是简单的介绍,想要非常详细的解析,可以建议看下这篇博客,写的非常的好下面给处传送门:
http://blog.csdn.net/u010961631/article/details/14227421
由于我现在也是刚开始接触源代码,对系统层不是很了解,而且ContentProvider涉及到系统层的非常多,所以也不打算目前做了解。只是简单的做个介绍:
这里对于ContentProvider的基本用法不做介绍,不懂得话可以看下我的另外一篇博客:
http://blog.csdn.net/simon_crystin/article/details/68517050
下面就开始我是怎么追踪源代码的:
首先我们看 这个方法:
getContentResolver().insert(MyContentProvider.uri,contentValues);
我们先看看getContentResolver()这个方法:
public ContentResolver getContentResolver() { return mBase.getContentResolver(); }
继续往下面看 getContentResolver();
public abstract class Context public abstract ContentResolver getContentResolver();
这里定义了一个抽象方法,是Context下面的抽象方法。
肯定有个子类重写了这个方法,我们发现:class ContextImpl extends Context,
于是我们去搜索:
@Override public ContentResolver getContentResolver() { return mContentResolver; }
果然在下面找到了这个方法。接着往下面看:
private final ApplicationContentResolver mContentResolver;
这里返回的是ApplicationContentResolver 的对象。
private static final class ApplicationContentResolver extends ContentResolver
ApplicationContentResolver 继承自ContentResolver;
这就到了我们熟悉的地方了。终于是获得了ContentResolver 的对象。
我们去这下面找insert方法:
public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url, @Nullable ContentValues values) { Preconditions.checkNotNull(url, "url"); IContentProvider provider = acquireProvider(url); if (provider == null) { throw new IllegalArgumentException("Unknown URL " + url); } try { long startTime = SystemClock.uptimeMillis(); Uri createdRow = provider.insert(mPackageName, url, values); long durationMillis = SystemClock.uptimeMillis() - startTime; maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */); return createdRow; } catch (RemoteException e) { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { releaseProvider(provider); } }
这个方法做了什么操作呢?
IContentProvider provider = acquireProvider(url);
我们可以看到这个代码,我之前的理解是,通过Uri来获取ContentProvider对象(通过Uri来区分不同的对象,这个是比较基础的),如果这样想的话,那就有点低估Google工程师了。
这里我们再跟下去,看看acquireProvider()这个方法到底是怎么样呢?
public final IContentProvider acquireProvider(Uri uri) { if (!SCHEME_CONTENT.equals(uri.getScheme())) { return null; } final String auth = uri.getAuthority(); if (auth != null) { return acquireProvider(mContext, auth); } return null; }
很显然,返回的一个对象,但是这个对象到底是什么呢?我们继续:
protected abstract IContentProvider acquireProvider(Context c, String name);
这个时候,可以看到,这是一个抽象方法,那肯定在子类重写了。。
在前面的提到ApplicationContentResolver这个类中,我们找到了这个重写的方法:
protected IContentProvider acquireProvider(Context context, String auth) { return mMainThread.acquireProvider(context, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), true); }
这里我们可以看到,返回了一个ContentProvider。当然,还可以继续追下去,不过博主技能有限,并且对系统层不了解。就不再进行了解了。不过目前正在学系统层这一块。
整个流程:
1、当我们调用getContentResolver().insert()后,将会通过getContentResolver()得到ContentResolver对象,然后调用该对象的insert()方法。 2、在ContentResolver中,会通过acquireProvider()的方法得到IContentProvider对象,而这个对象的获取首先需要ActivityThread中向ActivityManagerService申请的ContentProvider的详细信息(ContentProviderHolder),然后利用这个Holder去得到(getIContentProvider)ContentProvider的远程代理对象(Transport对象)。 3、拿到这个对象之后,调用其insert方法,该方法将会由ContentProvider传递给其子类(AbstractContactsProvider),并在子类中将insert操作转换为事务处理的方式(InsertInTransaction),AbstractContactsProvider中虽然将处理方式转换成事务的方式,但是却没有具体的实现,而是把具体的操作留给其子类(ContactsProvider2)完成。 4、ContactsProvider2在实现过程中将会用相应的SQLiteOpenHelper去把操作转换成具体的SQLite语句并执行。
相关文章推荐
- Android四大组件之内容提供者--ContentProvider
- Android四大组件之内容提供者--ContentProvider
- 【Android学习之道】 四大组件之ContentProvider内容提供器
- Android四大组件ContentProvider 内容提供者
- Android之四大组件之一-ContentProvider内容提供者的使用(二)
- Android 的四大组件Content Provider内容提供者
- Android 组件ContentProvider(一)内容提供器
- Android四大组件之一之内容提供者ContentProvider
- Android四大组件之 内容提供器Content Provider
- Android组件系列----ContentProvider内容提供者【4】
- Android组件系列----ContentProvider内容提供者【1】
- Android四大组件之ContentProvider(内容提供者)02
- Android四大组件之内容提供者ContentProvider
- Android组件系列----ContentProvider内容提供者【4】
- Android四大组件之ContentProvider(内容提供者)01
- Android四大组件之一ContentProvider(内容提供者)
- android四大组件之一内容提供者contentprovider
- Android基础之四大组件-ContentProvider(内容提供者)
- Androidc学习笔记五之四大组件之内容提供器ContentProvider
- Android四大组件之一,内容提供器Content Provider详解