相关文章
Android深入理解四大组件系列
前言
Content Provider做为四大组件之一,通常情况下并没有其他的组件使用频繁,但这不能作为我们不去深入学习它的理由。关于Content Provider一篇文章是写不完的,这一篇文章先来介绍它的启动过程。
1.query方法到AMS的调用过程
在Android IPC机制(四)用ContentProvider进行进程间通信这篇文章我举了一个Content Provider使用的例子,在Activity中我是使用如下代码调用Content Provider的:
public class ContentProviderActivity extends AppCompatActivity {
private final static String TAG = "ContentProviderActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content_provider);
Uri uri = Uri.parse("content://com.example.liuwangshu.mooncontentprovide.GameProvider");
ContentValues mContentValues = new ContentValues();
mContentValues.put("_id", 2);
mContentValues.put("name", "大航海时代ol");
mContentValues.put("describe", "最好玩的航海网游");
getContentResolver().insert(uri, mContentValues);//1
Cursor gameCursor = getContentResolver().query(uri, new String[]{"name", "describe"}, null, null, null);
...
}
}
要想调用Content Provider,首先需要使用注释1处的getContentResolver方法,如下所示。
frameworks/base/core/Java/android/content/ContextWrapper.java
Override
public ContentResolver getContentResolver() {
return mBase.getContentResolver();
}
这里mBase指的是ContextImpl,ContextImpl的getContentResolver方法如下所示。
frameworks/base/core/java/android/app/ContextImpl.java
@Override
public ContentResolver getContentResolver() {
return mContentResolver;
}
上面的代码return了ApplicationContentResolver类型的mContentResolver对象,ApplicationContentResolver是ContextImpl中的静态内部类,继承自ContentResolver,它在ContextImpl的构造方法中被创建。
当我们调用ContentResolver的insert、query、update等方法时就会启动Content Provider,这里拿query方法来进行举例。
query方法的实现在ApplicationContentResolver的父类ContentResolver中,代码如下所示。
frameworks/base/core/java/android/content/ContentResolver.java
public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
@Nullable String[] projection, @Nullable String selection,
@Nullable String[] selectionArgs, @Nullable String sortOrder,
@Nullable CancellationSignal cancellationSignal) {
Preconditions.checkNotNull(uri, "uri");
IContentProvider unstableProvider = acquireUnstableProvider(uri);//1
...
try {
...
try {
qCursor = unstableProvider.query(mPackageName, uri, projection,
selection, selectionArgs, sortOrder, remoteCancellationSignal);//2
} catch (DeadObjectException e) {
...
}
...
}
在注释1处通过acquireUnstableProvider方法返回IContentProvider类型的unstableProvider对象,在注释2处调用unstableProvider的query方法。我们查看acquireUnstableProvider方法做了什么,如下所示。
frameworks/base/core/java/android/content/ContentResolver.java
public final IContentProvider acquireUnstableProvider(Uri uri) {
if (!SCHEME_CONTENT.equals(uri.getScheme())) {//1
return null;
}
String auth = uri.getAuthority();
if (auth != null) {
return acquireUnstableProvider(mContext, uri.getAuthority());//2
}
return null;
}
注释1处用来检查Uri的scheme是否等于”content”,如果不是则返回null。注释2处调用了acquireUnstableProvider方法,这是个抽象方法,它的实现在ContentResolver的子类ApplicationContentResolver中:
frameworks/base/core/java/android/app/ContextImpl.java
@Override
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
return mMainThread.acquireProvider(c,
ContentProvider.getAuthorityWithoutUserId(auth),
resolveUserIdFromAuthority(auth), false);
}
return了ActivityThread类型的mMainThread对象的acquireProvider方法:
frameworks/base/core/java/android/app/ActivityThread.java
public final IContentProvider acquireProvider(
Context c, String auth, int userId, boolean stable) {
final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);//1
if (provider != null) {
return provider;
}
IActivityManager.ContentProviderHolder holder =