android数据库更新简介


  1. 概述

    Android应用程序组件Content Provider中的数据更新通知机制和Android系统中的广播通知机制的有点类似。它们有三个主要区别,区别一是前者是通过URI来把通知的发送者和接收者关联在一起的,而后者是通过intent来关联的;二是前者的通知注册中心是由ContentService服务来扮演,而后者是由ActivityManagerService服务来扮演的;三是前者负责接收数据更新通知的类必须要继承ContentObserver类,而后者要继承BroadcastReceiver类。下面分三个部分来分析数据更新流程。1ContentService的启动过程;2、监控数据变化的ContentObserver的注册过程;3、数据更新通知的发送过程。

  2. ContentService的启动过程

    Android系统进程Zygote在启动的时候,会加载系统的一些关键服务,ContentService就这些关键服务之一。如图所示:

        private static final String CONTENT_SERVICE_CLASS =
                "com.android.server.content.ContentService$Lifecycle";
    mSystemServiceManager.startService(CONTENT_SERVICE_CLASS);
    public final class ContentService extends IContentService.Stub {
        static final String TAG = "ContentService";
        static final boolean DEBUG = false;
    
        public static class Lifecycle extends SystemService {
            private ContentService mService;
    
            public Lifecycle(Context context) {
                super(context);
            }
    
            @Override
            public void onStart() {
                final boolean factoryTest = (FactoryTest
                        .getMode() == FactoryTest.FACTORY_TEST_LOW_LEVEL);
                mService = new ContentService(getContext(), factoryTest);
                publishBinderService(ContentResolver.CONTENT_SERVICE_NAME, mService);
            }

        protected final void publishBinderService(String name, IBinder service) {
            publishBinderService(name, service, false);
        }
    
        /**
         * Publish the service so it is accessible to other services and apps.
         */
        protected final void publishBinderService(String name, IBinder service,
                boolean allowIsolated) {
            ServiceManager.addService(name, service, allowIsolated);
        }

    可以看出,在ContentService的内部类Lifecycle类的onStart函数中,会创建ContentService实例,然后把它添加到ServiceManager中去,这样ContentService服务就启动起来了,其他地方就可以通过ServiceManager来获得它的一个远程接口来使用它提供的服务。

  3. ContentOberver的注册过程

    在应用层注册观察者需要继承ContentObserver并实现onChange函数。当这个ContentObserver子类负责监控的数据发生变化时,ContentService就会调用它的onChange函数来处理。注册过程如下:

        public void registerContentObserver(Uri uri, boolean notifyForDescendants,
                                            IContentObserver observer, int userHandle) {
            synchronized (mRootNode) {
                mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
                        uid, pid, userHandle);
                if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
                        " with notifyForDescendants " + notifyForDescendants);
            }

    最后调用了ContentService类的成员变量mRootNodeaddObserverLocked函数来注册这个ContentObserver对象observer,成员变量mRootNode的类型为ContentService在内部定义的一个类ObserverNode。注册到ContentService中的ContentObserver按照树形来组织,树的节点类型为ObserverNode,而树的根节点就为ContentService类的成员变量mRootNode,每一个ObserverNode节点都对应一个名字,它是从URI中解析出来的。

  4. 数据更新通知的发送过程

    在联系人数据库的增删改查操作都会发出通知,如下:

        public Uri insert(Uri uri, ContentValues values) {
            ContactsTransaction transaction = startTransaction(false);
            try {
                Uri result = insertInTransaction(uri, values);
                if (result != null) {
                    transaction.markDirty();
                }
                transaction.markSuccessful(false);
                return result;
            } finally {
                endTransaction(false);
            }
        }
        private void endTransaction(boolean callerIsBatch) {
            ContactsTransaction transaction = mTransactionHolder.get();
            if (transaction != null && (!transaction.isBatch() || callerIsBatch)) {
                try {
                    if (transaction.isDirty()) {
                        notifyChange();
                    }
                } 
            }
        }

        protected void notifyChange() {
            notifyChange(mSyncToNetwork);
            mSyncToNetwork = false;
        }
    
        protected void notifyChange(boolean syncToNetwork) {
            getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null,
                    syncToNetwork);
        }

    从上面可看出在content provider中会调用notifyChange来通知那些注册了监控content://com.android.contacts这个URIContentObserver,它监控的数据发生变化了。

    最后还是调用到了ContentService中:

        public void notifyChange(Uri uri, IContentObserver observer,
                                 boolean observerWantsSelfNotifications, int flags,
                                 int userHandle) {
            try {
                ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
                synchronized (mRootNode) {
                    mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
                            flags, userHandle, calls);
                }
                final int numCalls = calls.size();
                for (int i=0; i<numCalls; i++) {
                    ObserverCall oc = calls.get(i);
                    try {
                        oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
                        if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at "
                                + uri);
                    } 
                }
        }

    这里会先调用collectObserverLocked函数来手机那些注册了上面URIContentObserver,然后分别调用这些ContentObserveronChange函数来通知它们监控的数据发生变化了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值