基于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来发起真正的同步过程。 









 

posted @ 2013-07-01 21:29  爱生活,爱编程  阅读(871)  评论(0编辑  收藏  举报