`
wxlgzxx_1988
  • 浏览: 69101 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Android ContentProvider

阅读更多

(一) 前言
ContentProvider是android组件之一,可以提供数据的跨应用程序访问,提供数据的跨进程无缝隙访问,所以是非常重要的东东。使用方法一般是

复制内容到剪贴板
代码:
getContentResolver().query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);

那么下面来提几个问题:
1. 在应用程序A里面怎么跨进程拿到ContentProvider的对象呢?
2. ContentProvider实例对象是保存在哪里呢?
3. ContentProvider的方法实现要注意线程安全吗?

如果你能很清晰的回答这几个问题,那么下面的你就不需要继续看了,如果还有疑问,咱们一起往下面学习吧~

(二) 怎么跨进程拿到ContentProvider的对象
1. 我们来看ContentResolver.query方法是怎么实现的
a. 首先它会去找ContentProvider对象,是这样写的

复制内容到剪贴板
代码:
IContentProvider unstableProvider = acquireUnstableProvider(uri);

b. 然后acquireUnstableProvider(uri)方法是这样的:

复制内容到剪贴板
代码:
public final IContentProvider acquireUnstableProvider(Uri uri) {
        if (!SCHEME_CONTENT.equals(uri.getScheme())) {
            return null;
        }
        String auth = uri.getAuthority();//取得ContentProvider名字,拿这个名字去寻找对应的ContentProvider
        if (auth != null) {
            return acquireUnstableProvider(mContext, uri.getAuthority());
        }
        return null;
    }

在这段代码里面,关键地方在这里 String auth = uri.getAuthority();这里取得的auth就是我们在AndroidManifes.xml文件中配置的ContentProvider的android:authorities的值
如:

复制内容到剪贴板
代码:
<provider android:name=".TestProvider"
                android:authorities="com.android.test"></provider>

所以,这个android:authorities属性配置的就是该ContentProvider的名字,是它在Android系统中的名字,我们是通过这个名字去找对应的ContentProvider对象的。

c. ok..既然现在我们拿到ContentProvider的名字了,我们就来看看acquireUnstableProvider方法怎么通过名字来找到ContentProvider对象的。
这个acquireUnstableProvider方法会调用到ActivityThread的acquireProvider方法,这个方法的实现是:

复制内容到剪贴板
代码:
public final IContentProvider acquireProvider(Context c, String name, boolean stable) {
        IContentProvider provider = acquireExistingProvider(c, name, stable);
        if (provider != null) {
            return provider;
        }

        // There is a possible race here.  Another thread may try to acquire
        // the same provider at the same time.  When this happens, we want to ensure
        // that the first one wins.
        // Note that we cannot hold the lock while acquiring and installing the
        // provider since it might take a long time to run and it could also potentially
        // be re-entrant in the case where the provider is in the same process.
        IActivityManager.ContentProviderHolder holder = null;
        try {
            holder = ActivityManagerNative.getDefault().getContentProvider(
                    getApplicationThread(), name, stable);
        } catch (RemoteException ex) {
        }
        if (holder == null) {
            Slog.e(TAG, "Failed to find provider info for " + name);
            return null;
        }

        // Install provider will increment the reference count for us, and break
        // any ties in the race.
        holder = installProvider(c, holder, holder.info,
                true /*noisy*/, holder.noReleaseNeeded, stable);
        return holder.provider;
    }

这里就是查找ContentProvider实现的精髓所在了。。
首先,它去找acquireExistingProvider方法,这个方法其实就是根据我们传过来的名称在一个map里面找,如:
ProviderClientRecord pr = mProviderMap.get(name);
由于我们的ActivityThread和我们的应用程序还在一个进程里面,所以这个步骤我们可以理解为:在本地缓存中寻找ContentProvider对象
ok...在本地找了之后,如果找到了,就直接返回。
if (provider != null) {
            return provider;
        }
如果没有找到,就继续往下面走:
holder = ActivityManagerNative.getDefault().getContentProvider(
                    getApplicationThread(), name, stable);
这个方法就是调用到ActivityManagerService的getContentProvider方法去寻找ContentProvider.这里是一个跨进程调用,因为ActivityThread和ActivityManagerService不在一个进程里面。
至于ActivityThread和ActivityManagerService的关系,可以参考我以前的这篇帖子:
http://bbs.51cto.com/thread-1008812-1.html

而ActivityManagerService会把所有的ContentProvider都实例化出来,并且缓存在一个map里面,所以我们就可以通过

复制内容到剪贴板
代码:
holder = ActivityManagerNative.getDefault().getContentProvider(
                    getApplicationThread(), name, stable);

从ActivityManagerService远程得到一个ContentProvider对象。那么这一步,我们可以理解为:从远程服务中寻找ContentProvider对象
ok..从远程ActivityManagerService得到ContentProvider对象之后,我们继续往下面走。

复制内容到剪贴板
代码:
holder = installProvider(c, holder, holder.info,
                true /*noisy*/, holder.noReleaseNeeded, stable);
        return holder.provider;

首先,会调用installProvider方法,这个方法其实就是往本地的ContentProvider map缓存中添加一条缓存记录。
ok...那么这整个过程,我们就可以理解为这样:
i.  第一步,它从ActivityThread里面本地缓存寻找ContentProvider对象,所以找到了,就一切ok..
ii. 第二步,如果第一步没有找到,那么就去ActivityManagerService远程服务中寻找ContentProvider对象。
iii.第三步,从远程服务中找到ContentProvider对象之后,就把这个对象缓存在本地,那么下次找的话,直接就可以从本地缓存中查找了。
那么,它为什么要有这个机制呢?个人猜测:因为跨进程调用是需要时间和资源消耗的,所以,它才有了本地缓存这么个东东。

(三) ContentProvider实例对象是保存在哪里
那么如果大家看完了上面一篇长篇大论,这个问题就很好回答了。
它储存在两个位置:
1. ActivityThread的本地map缓存中
2. ActivityManagerService的远程服务map缓存中

(四) ContentProvider的方法实现要注意线程安全吗
从上面一段描述来看,我们可以发现一个问题,ContentProvider在某种程度上是单例的,比如我们第一次从本地map缓存里面得到ContentProvider对象,第二次我们在同一个应用程序请求的时候,拿到的肯定是同一个缓存对象。
那么我们的ContentProvider的代码,比如查询,更新,删除等等,必须注意线程安全的问题。
那么单例下,我们怎么注意线程安全问题呢?
1. ContentProvider尽量少用成员变量,因为我们用的是单例,所以成员变量是共享的。
2. 所以真的用到了共享资源,建议用synchronized或者TheadLocal来解决。至于synchronized和TheadLocal的区别,这篇文章就不讨论了,下次有机会再写吧。。

分享到:
评论

相关推荐

    Android ContentProvider全面解析

    在Android系统中,ContentProvider是四大组件之一,它扮演着数据共享和访问的重要角色。ContentProvider使得应用程序可以将自己的数据结构暴露给其他应用,同时也能够访问其他应用公开的数据。本篇文章将全面解析...

    android ContentProvider Demo

    在Android开发中,ContentProvider是一种重要的组件,它允许应用程序之间共享数据。本示例"android ContentProvider Demo"将深入探讨如何创建和使用ContentProvider来实现跨应用的数据交换。ContentProvider作为...

    Android ContentProvider简单实现

    在Android开发中,ContentProvider是四大组件之一,它充当了数据共享的桥梁,使得不同的应用程序之间可以安全地访问和共享数据。本篇文章将详细介绍如何在Android中实现一个简单的ContentProvider。 首先,理解...

    Android+Room+ContentProvider

    在Android应用开发中,数据持久化是一个至关重要的环节,而Android Room和ContentProvider是其中的两个关键组件。本文将深入探讨这两个技术,并结合实际案例,解释如何在Android应用中使用它们来管理和共享SQLite...

    免费下载:android ContentProvider详细解析

    ### android ContentProvider 详解 #### 一、ContentProvider 概述 ContentProvider 是 Android 四大组件之一,它主要用于在不同的应用程序之间实现数据共享。在 Android 中,每个应用程序都有自己的私有存储空间...

    基于Android ContentProvider的总结详解

    【Android ContentProvider详解】 ContentProvider是Android系统提供的一种机制,使得不同应用程序之间可以安全地共享数据。通过ContentProvider,开发者可以将自己的数据集暴露出来,供其他应用查询、添加、删除和...

    android contentprovider的例子

    在Android应用开发中,ContentProvider是一个至关重要的组件,它扮演着数据共享的角色,使得不同的应用程序之间可以安全地读写共享数据。"android contentprovider的例子"这个主题将带你深入理解ContentProvider的...

    android contentprovider的使用总结

    在Android开发中,ContentProvider是四大组件之一,它充当了一个数据共享的桥梁,使得不同的应用程序之间可以安全地访问和操作数据。本篇文章将深入探讨如何使用ContentProvider进行数据库的增删改查操作,并结合...

    android contentprovider

    在Android系统中,ContentProvider是四大组件之一,它扮演着数据共享和跨应用数据访问的角色。ContentProvider使得应用程序可以将自己的数据结构公开,让其他应用程序能够按照统一的方式进行读写操作,实现了不同...

    android 用ContentProvider操作文件

    在Android系统中,ContentProvider是一种核心组件,它允许应用程序之间共享数据,而无需直接访问对方的内部存储。在本教程中,我们将深入探讨如何利用ContentProvider来操作文件,以及其在跨应用数据传输中的作用。 ...

    android contentprovider使用示例

    在Android开发中,ContentProvider是四大组件之一,它充当了数据共享的桥梁,使得不同的应用程序之间可以安全地访问和操作数据。本示例将详细解释如何在Android中使用ContentProvider。 1. **ContentProvider基本...

    Android ContentProvider 使用详解源码

    在Android系统中,ContentProvider是实现跨应用数据共享的关键组件,它允许应用程序暴露自己的数据集,使得其他应用可以通过标准的接口进行访问。本教程将深入解析ContentProvider的使用及其源码,结合SQLite数据库...

    Android contentprovider总结

    ### Android ContentProvider 总结 #### 一、ContentProvider 概述 ContentProvider 是 Android 四大组件之一,主要用于在不同的应用程序之间实现数据共享。它通过定义一套标准接口,允许其他应用通过这些接口来...

    Android ContentProvider的使用

    在Android应用开发中,ContentProvider是一个非常重要的组件,它扮演着数据共享和访问的角色。ContentProvider使得不同应用程序之间可以安全地共享数据,就像数据库一样,但又超越了数据库的范畴,因为它提供了统一...

    android contentprovider的使用

    在Android开发中,ContentProvider是Android四大组件之一,它的主要职责是实现应用程序间的数据共享。ContentProvider通过统一的接口让其他应用能够访问和修改特定的数据集,这些数据可能存储在SQLite数据库、文件...

    android ContentProvider内容提供者

    在Android开发中,ContentProvider是四大组件之一,它充当了应用程序间数据共享的桥梁。ContentProvider使得一个应用的数据可以被其他应用访问,同时也为数据提供了统一的接口。本篇文章将深入探讨ContentProvider的...

    Android中ContentProvider的示例

    在Android系统中,ContentProvider是四大组件之一,它扮演着数据共享的角色,使得不同应用程序间可以安全地交换数据。本示例将深入讲解如何创建和使用ContentProvider。 首先,我们来理解ContentProvider的基本概念...

Global site tag (gtag.js) - Google Analytics