• 基于Andoird 4.2.2的同步框架源代码学习——同步提供端


    Android同步框架

    同步(synchronization)允许用户将远程数据下载到新的设备上,同时将设备上的帐户数据上传到远端。同步还保证用户能够看到最新的数据。
    开发者自然可以通过自己的方式来设计实现同步机制。但是Android系统还是提供了一个可插拔的同步框架。这个框架自动化的执行以下任务:
    • 检查网络可用性
    • 根据用户设定的选项规划、执行同步
    • 重启已经停止的同步
    开发者需要向这个框架提供自己定义的同步适配器(Sync adapter)插件。一个sync adapter唯一的与某个servive/content provider相关联。但是后者反过来可以对应多个sync adapter。
     

    SyncAdapter

    首先,Android framework尽可能的封装了数据同步相关的共性操作,而将针对特定服务的同步逻辑的具体实现留给了应用程序。这一点具体体现在Android framework提供的

    AbstractThreadedSyncAdapter抽象类上。对照官方文档中的描述,在应用开发中提供一个自定义的sync adapter,只需要完成下面的几个步骤:

     

    • 扩展AbstractThreadedSyncAdapter抽象类,实现它的onPerformSync()抽象方法
    • 在res/xml下创建一个XML文件来描述这个sync adapter
    • 在应用中创建一个service,使之处理名为“android.content.SyncAdapter”的动作

    详细步骤可见AbstractThreadedSyncAdapter类的参考文档。

    这里主要分析一下AbstractThreadedSyncAdapter类本身,也即是sync adapter的共性部分。

    看看参与sync adapter调用的类簇:

     

    下面是启动一次同步的序列图:

     

    简要描述一下:

    ISyncAdapter

    首先,sync adapter的行为通过ISyncAdapter接口来描述:

     

    /**
     * Interface used to control the sync activity on a SyncAdapter
     * @hide
     */
    oneway interface ISyncAdapter {
        /**
         * Initiate a sync for this account. SyncAdapter-specific parameters may
         * be specified in extras, which is guaranteed to not be null.
         *
         * @param syncContext the ISyncContext used to indicate the progress of the sync. When
         *   the sync is finished (successfully or not) ISyncContext.onFinished() must be called.
         * @param authority the authority that should be synced
         * @param account the account that should be synced
         * @param extras SyncAdapter-specific parameters
         */
        void startSync(ISyncContext syncContext, String authority,
          in Account account, in Bundle extras);
    
        /**
         * Cancel the most recently initiated sync. Due to race conditions, this may arrive
         * after the ISyncContext.onFinished() for that sync was called.
         * @param syncContext the ISyncContext that was passed to {@link #startSync}
         */
        void cancelSync(ISyncContext syncContext);
    
        /**
         * Initialize the SyncAdapter for this account and authority.
         *
         * @param account the account that should be synced
         * @param authority the authority that should be synced
         */
        void initialize(in Account account, String authority);
    }

    AbstractThreadedSyncAdapter类中提供一个ISyncAdapter接口的本地服务:

     

        private class ISyncAdapterImpl extends ISyncAdapter.Stub {
            public void startSync(ISyncContext syncContext, String authority, Account account,
                    Bundle extras) {
                ...
            }
    
            public void cancelSync(ISyncContext syncContext) {
                ...
            }
    
            public void initialize(Account account, String authority) throws RemoteException {
                ...
            }
        }

    并且定义了向外部提供IBinder实例的方法:

     

        /**
         * @return a reference to the IBinder of the SyncAdapter service.
         */
        public final IBinder getSyncAdapterBinder() {
            return mISyncAdapterImpl.asBinder();
        }

    ISyncAdapter.startSync()

     

            public void startSync(ISyncContext syncContext, String authority, Account account,
                    Bundle extras) {
                ...
                synchronized (mSyncThreadLock) {
                    if (!mSyncThreads.containsKey(threadsKey)) {
                        ...
                        SyncThread syncThread = new SyncThread(
                                "SyncAdapterThread-" + mNumSyncStarts.incrementAndGet(),
                                syncContextClient, authority, account, extras);
                        mSyncThreads.put(threadsKey, syncThread);
                        syncThread.start();
                        ...
                    }
                    ...
                }
                ...
            }

    其实现方式是通过启动一个独立的线程来发起同步。


    SyncThread

     

        private class SyncThread extends Thread {
            private final SyncContext mSyncContext;
            private final String mAuthority;
            private final Account mAccount;
            private final Bundle mExtras;
            private final Account mThreadsKey;
            ...
    
            @Override
            public void run() {
                ...
                try {
                    ...
                    provider = mContext.getContentResolver().acquireContentProviderClient(mAuthority);
                    if (provider != null) {
                        AbstractThreadedSyncAdapter.this.onPerformSync(mAccount, mExtras,
                                mAuthority, provider, syncResult);
                    } else {
                        syncResult.databaseError = true;
                    }
                } 
                ...
            }
            ...
        }

    这个独立线程的核心就是调用AbstractThreadedSyncAdapter.onPerformSync()方法来执行同步相关的业务逻辑。

    这样,总而言之,外界通过从系统中查找得到特定的Sync adapter service,然后通过绑定到这个service来获取ISyncAdapter服务的代理对象。然后调用代理对象来启动/终止同步操作。代理对象与提供同步实现的应用程序进程进行IPC来发起真正的同步过程。 









  • 相关阅读:
    解决浏览器兼容改内容的函数
    iPhone 和Android应用,特殊的链接:打电话,短信,email
    ArrayList和LinkedList的区别
    关于HashTable,HashMap和TreeMap的几点心得
    Android开发--List与ArrayList区别
    Android 版本升级涉及到的数据库数据迁移问题
    深入理解Android的startservice和bindservice
    Android之Activity的四种启动模式
    控制反转与依赖注入
    vi/vim基本使用方法
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3165904.html
Copyright © 2020-2023  润新知