美文网首页
ContentService:第二部分数据同步

ContentService:第二部分数据同步

作者: 81bad73e9053 | 来源:发表于2016-09-20 19:10 被阅读272次

    3.数据同步机制之SyncManager

    同步策略

    3.1SyncManager的理解

    3.1.1SyncAdapterCache类的分析

    找出metadata和attribute为指定类型的xml节点数据,并放到存储文件中
    /data/system/registered_services/android.content.SyncAdapter.xml

    例如davdroid的manifest文件中有以下内容

            <service
                android:name=".syncadapter.CalendarsSyncAdapterService"
                android:exported="true"
                android:process=":sync"
                tools:ignore="ExportedService">
                <intent-filter>
                    <action android:name="android.content.SyncAdapter"/>
                </intent-filter>
    
                <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/sync_calendars"/>
            </service>
            <service
                android:name=".syncadapter.TasksSyncAdapterService"
                android:exported="true"
                android:process=":sync"
                tools:ignore="ExportedService">
                <intent-filter>
                    <action android:name="android.content.SyncAdapter"/>
                </intent-filter>
    
                <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/sync_tasks"/>
            </service>
    

    /data/system/registered_services/android.content.SyncAdapter.xml的文件内容

    <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
    <services>
    <service uid="10049" authority="com.example.android.network.sync.basicsyncadapter" accountType="com.example.android.network.sync.basicsyncadapter" />
    <service uid="10016" authority="com.android.contacts" accountType="com.android.exchange" />
    <service uid="10015" authority="com.android.email.provider" accountType="com.android.email" />
    <service uid="10016" authority="com.android.email.provider" accountType="com.android.exchange" />
    <service uid="10016" authority="com.android.calendar" accountType="com.android.exchange" />
    <service uid="10052" authority="com.android.calendar" accountType="bitfire.at.davdroid" />
     <service uid="10052" authority="org.dmfs.tasks" accountType="bitfire.at.davdroid" />
    </services>
    
    

    SyncAdapterCache继承自RegisteredServicesCache
    并将需要解析和存储的类型传递给了RegisteredServicesCache

    public class SyncAdaptersCache extends RegisteredServicesCache<SyncAdapterType> {
        private static final String TAG = "Account";
    
        private static final String SERVICE_INTERFACE = "android.content.SyncAdapter";
        private static final String SERVICE_META_DATA = "android.content.SyncAdapter";
        private static final String ATTRIBUTES_NAME = "sync-adapter";
        private static final MySerializer sSerializer = new MySerializer();
    
        public SyncAdaptersCache(Context context) {
            super(context, SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME, sSerializer);
        }
    
        public SyncAdapterType parseServiceAttributes(Resources res,
                String packageName, AttributeSet attrs) {
            TypedArray sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.SyncAdapter);
            try {
                final String authority =
                        sa.getString(com.android.internal.R.styleable.SyncAdapter_contentAuthority);
                final String accountType =
                        sa.getString(com.android.internal.R.styleable.SyncAdapter_accountType);
                if (authority == null || accountType == null) {
                    return null;
                }
                final boolean userVisible =
                        sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_userVisible, true);
                final boolean supportsUploading =
                        sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_supportsUploading,
                                true);
                final boolean isAlwaysSyncable =
                        sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_isAlwaysSyncable,
                                false);
                final boolean allowParallelSyncs =
                        sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_allowParallelSyncs,
                                false);
                final String settingsActivity =
                        sa.getString(com.android.internal.R.styleable
                                .SyncAdapter_settingsActivity);
                return new SyncAdapterType(authority, accountType, userVisible, supportsUploading,
                        isAlwaysSyncable, allowParallelSyncs, settingsActivity);
            } finally {
                sa.recycle();
            }
        }
    
        static class MySerializer implements XmlSerializerAndParser<SyncAdapterType> {
            public void writeAsXml(SyncAdapterType item, XmlSerializer out) throws IOException {
                out.attribute(null, "authority", item.authority);
                out.attribute(null, "accountType", item.accountType);
            }
    
            public SyncAdapterType createFromXml(XmlPullParser parser)
                    throws IOException, XmlPullParserException {
                final String authority = parser.getAttributeValue(null, "authority");
                final String accountType = parser.getAttributeValue(null, "accountType");
                return SyncAdapterType.newKey(authority, accountType);
            }
        }
    }
    
    

    3.1.2SyncQueue的分析

        private final HashMap<String, SyncOperation> mOperationsMap = Maps.newHashMap();
    
        public SyncQueue(SyncStorageEngine syncStorageEngine, final SyncAdaptersCache syncAdapters) {
            mSyncStorageEngine = syncStorageEngine;
            mSyncAdapters = syncAdapters;
        }
    
        public void addPendingOperations(int userId) {
            //mSyncStorageEngine取出上次没有完成的同步信息,这些信息由PendingOperation 表示
            for (SyncStorageEngine.PendingOperation op : mSyncStorageEngine.getPendingOperations()) {
                if (op.userId != userId) continue;
                //从mSyncStorageEngine中取出该同步操作的backoff信息
                final Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(
                        op.account, op.userId, op.authority);
                //从SyncAdapterCache中取出该同步操作对应的Service信息
                //如果服务不存在则无需执行之后的流程
                final ServiceInfo<SyncAdapterType> syncAdapterInfo = mSyncAdapters.getServiceInfo(
                        SyncAdapterType.newKey(op.authority, op.account.type), op.userId);
                if (syncAdapterInfo == null) { 
                    continue;
                }
                //构造一个SyncOperation对象
                SyncOperation syncOperation = new SyncOperation(
                        op.account, op.userId, op.syncSource, op.authority, op.extras, 0 /* delay */,
                        backoff != null ? backoff.first : 0,
                        mSyncStorageEngine.getDelayUntilTime(op.account, op.userId, op.authority),
                        syncAdapterInfo.type.allowParallelSyncs());
                syncOperation.expedited = op.expedited;
                syncOperation.pendingOperation = op;
                add(syncOperation, op);//添加对象
            }
        }
    
    

    3.1.3StorageSyncEngine

    初始化的时候创建了一个目录并在该目录下新增了四个文件
    /data/system/sync
    /data/system/sync/accounts.xml账户信息
    /data/system/sync/pending.bin处于pending状态的同步请求
    /data/system/sync/status.bin状态信息
    /data/system/sync/stats.bin统计信息

    其中accounts.xml文件的内容在添加了davdroid后如下所示

    <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
    <accounts version="2" nextAuthorityId="93" offsetInSeconds="13093">
    <listenForTickles user="0" enabled="true" />
    <authority id="91" account="gwhexy@yutong.com" user="0" type="bitfire.at.davdroid" authority="com.android.calendar" enabled="true" syncable="true">
    <periodicSync period="60" />
    </authority>
    <authority id="92" account="gwhexy@yutong.com" user="0" type="bitfire.at.davdroid" authority="org.dmfs.tasks" enabled="false" syncable="false">
    <periodicSync period="86400" />
    </authority>
    </accounts>
    

    SyncStorageEngine的代码分析

        private SyncStorageEngine(Context context, File dataDir) {
            mContext = context;
            sSyncStorageEngine = this; 
            mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0")); 
            mDefaultMasterSyncAutomatically = mContext.getResources().getBoolean(
                   com.android.internal.R.bool.config_syncstorageengine_masterSyncAutomatically); 
            File systemDir = new File(dataDir, "system");
            File syncDir = new File(systemDir, "sync");
            syncDir.mkdirs();
            mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
            mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
            mPendingFile = new AtomicFile(new File(syncDir, "pending.bin"));
            mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
            //AtomicFile其实内部包括两个文件,其中一个用于数据备份
            readAccountInfoLocked();
            readStatusLocked();
            readPendingOperationsLocked();
            readStatisticsLocked();
            readAndDeleteLegacyAccountInfoLocked();
    
            writeAccountInfoLocked();
            writeStatusLocked();
            writePendingOperationsLocked();
            writeStatisticsLocked();
        }
    
        public static SyncStorageEngine newTestInstance(Context context) {
            return new SyncStorageEngine(context, context.getFilesDir());
        }
    
        public static void init(Context context) {
            if (sSyncStorageEngine != null) {
                return;
            }
            // This call will return the correct directory whether Encrypted File Systems is
            // enabled or not.
            File dataDir = Environment.getSecureDataDirectory();
            sSyncStorageEngine = new SyncStorageEngine(context, dataDir);
        }
    

    3.1.4SyncManager的分析

    SyncManger的几位成员的作用

    • SyncAdaptersCache用于管理系统中SyncService的信息,在SyncManager中,SyncService的信息用SyncAdapterType类表示
    • SyncOperation表示一次正在执行或者等待执行的同步操作,而SyncQueue通过mOperationsMap保存系统中存在的SyncOperation
    • SyncStorageEngine保存同步操作的信息,PendingOperation表示保存在本地文件中还没执行完的同步操作,SyncStorageEngine还会对同步操作做统计,如耗电量统计等。
        public SyncManager(Context context, boolean factoryTest) { 
            mContext = context;
    
            SyncStorageEngine.init(context);
            mSyncStorageEngine = SyncStorageEngine.getSingleton();
            mSyncStorageEngine.setOnSyncRequestListener(new OnSyncRequestListener() {
                public void onSyncRequest(Account account, int userId, String authority,
                        Bundle extras) {
                    scheduleSync(account, userId, authority, extras, 0, false);
                }
            });
    
            mSyncAdapters = new SyncAdaptersCache(mContext);
            mSyncQueue = new SyncQueue(mSyncStorageEngine, mSyncAdapters);
    
            HandlerThread syncThread = new HandlerThread("SyncHandlerThread",
                    Process.THREAD_PRIORITY_BACKGROUND);
            syncThread.start();
            mSyncHandler = new SyncHandler(syncThread.getLooper());
    
            mSyncAdapters.setListener(new RegisteredServicesCacheListener<SyncAdapterType>() {
                @Override
                public void onServiceChanged(SyncAdapterType type, int userId, boolean removed) {
                    if (!removed) {
                        scheduleSync(null, UserHandle.USER_ALL, type.authority, null, 0 /* no delay */,
                                false /* onlyThoseWithUnkownSyncableState */);
                    }
                }
            }, mSyncHandler);
           //创建一个intent,用于和AlarmManagerService交互
            mSyncAlarmIntent = PendingIntent.getBroadcast(
                    mContext, 0 /* ignored */, new Intent(ACTION_SYNC_ALARM), 0);
            //注册CONNECTIVITY_ACTION广播监听,同步操作需要使用网络传数据,所以此处需要监听广播
            IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
            context.registerReceiver(mConnectivityIntentReceiver, intentFilter);
    
            if (!factoryTest) {//监听重启广播
                intentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
                context.registerReceiver(mBootCompletedReceiver, intentFilter);
            }
    
            intentFilter = new IntentFilter(ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
            context.registerReceiver(mBackgroundDataSettingChanged, intentFilter);
          //监听存储空间广播,保存同步时一些信息存储到设备中
            intentFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW);
            intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
            context.registerReceiver(mStorageIntentReceiver, intentFilter);
    
            intentFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
            intentFilter.setPriority(100);
            context.registerReceiver(mShutdownIntentReceiver, intentFilter);
    
            intentFilter = new IntentFilter();
            intentFilter.addAction(Intent.ACTION_USER_REMOVED);
            intentFilter.addAction(Intent.ACTION_USER_STARTING);
            intentFilter.addAction(Intent.ACTION_USER_STOPPING);
            mContext.registerReceiverAsUser(
                    mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
    
            if (!factoryTest) {
                mNotificationMgr = (NotificationManager)
                    context.getSystemService(Context.NOTIFICATION_SERVICE);
                context.registerReceiver(new SyncAlarmIntentReceiver(),
                        new IntentFilter(ACTION_SYNC_ALARM));
            } else {
                mNotificationMgr = null;
            }
            mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
            mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    
           //创建wakelock,防止同步过程中掉电
            mHandleAlarmWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                    HANDLE_SYNC_ALARM_WAKE_LOCK);
            mHandleAlarmWakeLock.setReferenceCounted(false);
    
            // This WakeLock is used to ensure that we stay awake while running the sync loop
            // message handler. Normally we will hold a sync adapter wake lock while it is being
            // synced but during the execution of the sync loop it might finish a sync for
            // one sync adapter before starting the sync for the other sync adapter and we
            // don't want the device to go to sleep during that window.
            mSyncManagerWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                    SYNC_LOOP_WAKE_LOCK);
            mSyncManagerWakeLock.setReferenceCounted(false);
        //监听SyncStorageEngine状态变化
            mSyncStorageEngine.addStatusChangeListener(
                    ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, new ISyncStatusObserver.Stub() {
                public void onStatusChanged(int which) {
                    // force the sync loop to run if the settings change
                    sendCheckAlarmsMessage();
                }
            });
    
            if (!factoryTest) {//监听账户变化
                // Register for account list updates for all users
                mContext.registerReceiverAsUser(mAccountsUpdatedReceiver,
                        UserHandle.ALL,
                        new IntentFilter(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION),
                        null, null);
            }
    
            // Pick a random second in a day to seed all periodic syncs
            mSyncRandomOffsetMillis = mSyncStorageEngine.getSyncRandomOffset() * 1000;
        }
    
    
    

    3.2 ConentResolver的requestSync分析

    ** ConentResolver的requestSync方法用来发起一次同步请求**
    如发起邮件同步请求

    Account emailAccount = new Account("gwhexy@yutong.com","com.android.yutong");
    String emailAuthority = "com.android.email.provider";
    Bundle emialBundle = new Bundle();
    ...
    //发起email同步请求
    ContentResolver.requestSync(emailAccount,emailAuthority,emialBundle); 
    

    1.ContentResolver的requestSync方法

        public static void requestSync(Account account, String authority, Bundle extras) {
            if (extras == null) {
                throw new IllegalArgumentException("Must specify extras.");
            }
            SyncRequest request =
                new SyncRequest.Builder()
                    .setSyncAdapter(account, authority)
                    .setExtras(extras)
                    .syncOnce()
                    .build();
            requestSync(request);
        }
    
     
        public static void requestSync(SyncRequest request) {
            try {
                getContentService().sync(request);
            } catch(RemoteException e) {
                // Shouldn't happen.
            }
        }
    

    2.ContentService的requestSync方法i调用syncManager.scheduleSync

        public void requestSync(Account account, String authority, Bundle extras) {
            ContentResolver.validateSyncExtrasBundle(extras);
            int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
            try {
                SyncManager syncManager = getSyncManager();
                if (syncManager != null) {
                    syncManager.scheduleSync(account, userId, authority, extras, 0 /* no delay */,
                            false /* onlyThoseWithUnkownSyncableState */);
                }
            } finally {
                restoreCallingIdentity(identityToken);
            }
        }
    

    3.syncManager.scheduleSync

        /** 
         * @param requestedAccount  要进行同步操作的账户,如果为空,将同步所有账户
         * @param requestedAuthority 要同步的数据项,如果为空,表示全部同步
         * @param extras 同步操作中的参数信息
         * @param delay 延迟多少
         * @param onlyThoseWithUnkownSyncableState决定是否只是同步那些处于unknown状态的数据
         */
        public void scheduleSync(Account requestedAccount, int userId, String requestedAuthority,
                Bundle extras, long delay, boolean onlyThoseWithUnkownSyncableState) {
            boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
            //判断是否允许后台传输
            final boolean backgroundDataUsageAllowed = !mBootCompleted ||
                    getConnectivityManager().getBackgroundDataSetting();
    
            if (extras == null) extras = new Bundle();
    
            //同步服务中的参数信息
            //SYNC_EXTRAS_EXPEDITED参数表示是否立即执行,如果设置了该参数,则delay不起作用
            Boolean expedited = extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
            if (expedited) {
                delay = -1; // this means schedule at the front of the queue
            }
    
            AccountAndUser[] accounts;
            if (requestedAccount != null && userId != UserHandle.USER_ALL) {
                accounts = new AccountAndUser[] { new AccountAndUser(requestedAccount, userId) };
            } else {
               ccounts;
                if (accounts.length == 0) { 
                    return;
                }
            }
            //SYNC_EXTRAS_UPLOAD表示本次同步不是否上传,从本地同步到服务端是upload
            //反之为downlaod
            final boolean uploadOnly = extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false);
            //手动同步,如果是手动同步就忽略SYNC_EXTRAS_IGNORE_BACKOFF和SYNC_EXTRAS_IGNORE_SETTINGS
            final boolean manualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
            if (manualSync) {
                extras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true);
                extras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
            }
            final boolean ignoreSettings =
                    extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
            //本次同步操作的触发源头,触发源的目的是为了方便进行统计工作
            int source;
            if (uploadOnly) {
                source = SyncStorageEngine.SOURCE_LOCAL;
            } else if (manualSync) {
                source = SyncStorageEngine.SOURCE_USER;
            } else if (requestedAuthority == null) {
                source = SyncStorageEngine.SOURCE_POLL;
            } else {
                // this isn't strictly server, since arbitrary callers can (and do) request
                // a non-forced two-way sync on a specific url
                source = SyncStorageEngine.SOURCE_SERVER;
            }
    
            for (AccountAndUser account : accounts) {
                //从SyncAdapterCache中取出所有的SyncService信息
                final HashSet<String> syncableAuthorities = new HashSet<String>();
                for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter :
                        mSyncAdapters.getAllServices(account.userId)) {
                    syncableAuthorities.add(syncAdapter.type.authority);
                }
    
                //如果指定了本次同步的authority,就从同步服务中找出满足此authority的服务
                if (requestedAuthority != null) {
                    final boolean hasSyncAdapter = syncableAuthorities.contains(requestedAuthority);
                    syncableAuthorities.clear();
                    if (hasSyncAdapter) syncableAuthorities.add(requestedAuthority);
                }
                //取出syncable属性值,1为true,-1为unknown
                for (String authority : syncableAuthorities) {
                    int isSyncable = mSyncStorageEngine.getIsSyncable(account.account, account.userId,
                            authority);
                    if (isSyncable == 0) {
                        continue;
                    }
                    final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
                    syncAdapterInfo = mSyncAdapters.getServiceInfo(
                            SyncAdapterType.newKey(authority, account.account.type), account.userId);
                    if (syncAdapterInfo == null) {
                        continue;
                    }
                    final boolean allowParallelSyncs = syncAdapterInfo.type.allowParallelSyncs();
                    final boolean isAlwaysSyncable = syncAdapterInfo.type.isAlwaysSyncable();
                    //如果是unknown切永远是可同步的就设置为true              
                    if (isSyncable < 0 && isAlwaysSyncable) {
                        mSyncStorageEngine.setIsSyncable(account.account, account.userId, authority, 1);
                        isSyncable = 1;
                    }
                    //如果只能操作unkonwn但本次不是unknown,就不允许后续的操作
                    if (onlyThoseWithUnkownSyncableState && isSyncable >= 0) {
                        continue;
                    }
                    //如果同步服务不支持上传,但本次服务又需要上传,则不允许后续操作
                    if (!syncAdapterInfo.type.supportsUploading() && uploadOnly) {
                        continue;
                    }
    
                    // always allow if the isSyncable state is unknown
                    boolean syncAllowed =
                            (isSyncable < 0)
                            || ignoreSettings
                            || (backgroundDataUsageAllowed
                                    && mSyncStorageEngine.getMasterSyncAutomatically(account.userId)
                                    && mSyncStorageEngine.getSyncAutomatically(account.account,
                                            account.userId, authority));
                    if (!syncAllowed) { 
                        continue;
                    }
                    //取出backoff(backoff是指上次没有同步完成的多久之后延迟多少再次同步)
                    Pair<Long, Long> backoff = mSyncStorageEngine
                            .getBackoff(account.account, account.userId, authority);
                    long delayUntil = mSyncStorageEngine.getDelayUntilTime(account.account,
                            account.userId, authority);
                    final long backoffTime = backoff != null ? backoff.first : 0;
                    if (isSyncable < 0) {
                        Bundle newExtras = new Bundle();
                        newExtras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
     
                        scheduleSyncOperation(
                                new SyncOperation(account.account, account.userId, source, authority,
                                        newExtras, 0, backoffTime, delayUntil, allowParallelSyncs));
                    }
                    if (!onlyThoseWithUnkownSyncableState) {
      
                        scheduleSyncOperation(
                                new SyncOperation(account.account, account.userId, source, authority,
                                        extras, delay, backoffTime, delayUntil, allowParallelSyncs));
                    }
                }
            }
        }
    
     
    

    4.scheduleSyncOperation函数
    该方法内部将一个SyncOperation对象保存到SyncQueue中,然后发送MESSAGE_CHECK_ALARMS消息

    **5. MESSAGE_CHECK_ALARMS的消息处理流程 **

            public void handleMessage(Message msg) {
                long earliestFuturePollTime = Long.MAX_VALUE;
                long nextPendingSyncTime = Long.MAX_VALUE; 
                try {
                    waitUntilReadyToRun();
                    mDataConnectionIsConnected = readDataConnectionState();
                    mSyncManagerWakeLock.acquire(); //防止过程中掉电
                    //周期同步操作
                    earliestFuturePollTime = scheduleReadyPeriodicSyncs();
                    switch (msg.what) {  
                        ......
                        case SyncHandler.MESSAGE_CHECK_ALARMS:
                            //返回一个时间
                            nextPendingSyncTime = maybeStartNextSyncLocked();
                            break;
                    }
                } finally {
                    manageSyncNotificationLocked();
                    manageSyncAlarmLocked(earliestFuturePollTime, nextPendingSyncTime);
                    mSyncTimeTracker.update();
                    mSyncManagerWakeLock.release();
                }
            }
    

    6.maybeStartNextSyncLocked

    • 检查SyncQueue中SyncOperation,判断他们对应的同步服务的状态是否为false,是false就不再继续
    • 检查ConnectivityManagerService以判断同步目标是否使用了网络,如果没有使用网络,就不允许执行同步操作
    • 判断执行时间是否已到,如果未到,则不允许执行
    • 与当前正在执行的同步操作对象对比

    7.dispatchSyncOperation
    构建一个ActiveSyncContext对象,并将该对象绑定到同步服务上

    TU 8-16

    • 通过bindservice启动同步服务,在onServiceConnected函数中得到用于和SyncService交互的接口对象,也就是Binder通信的ISyncAdapter 的Bp端
    • ActiveSyncContext是ISyncContext解扣子Binder通信的Bn端,它调用ISyncAdapter的startSync时,会把自己同步给服务对象,同步服务得到的是ISyncContext的Bp端,当同步服务完成之后就调用ISyncContext的Bp端对象的onFinished函数通知ActiveSyncContext同步操作的结果

    8. ActiveSyncContext派发请求

            boolean bindToSyncAdapter(RegisteredServicesCache.ServiceInfo info, int userId) {
              
                Intent intent = new Intent();
                intent.setAction("android.content.SyncAdapter");
               设置目标服务的componentname 
               intent.setComponent(info.componentName);
                intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
                        com.android.internal.R.string.sync_binding_label);
                intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
                        mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0,
                        null, new UserHandle(userId)));
                mBound = true;
               bindService启动目标服务
                final boolean bindResult = mContext.bindService(intent, this,
                        Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
                        | Context.BIND_ALLOW_OOM_MANAGEMENT,
                        mSyncOperation.userId);
                if (!bindResult) {
                    mBound = false;
                }
                return bindResult;
            }
    

    当目标服务的onBind返回之后,ActiveSyncContext的onServiceConnected将被调用

            public void onServiceConnected(ComponentName name, IBinder service) {
                Message msg = mSyncHandler.obtainMessage();
                msg.what = SyncHandler.MESSAGE_SERVICE_CONNECTED;
                msg.obj = new ServiceConnectionData(this, ISyncAdapter.Stub.asInterface(service));
                mSyncHandler.sendMessage(msg);
            }
    

    消息处理函数中调用runBoundToSyncAdapter

                        case SyncHandler.MESSAGE_SERVICE_CONNECTED: {
                            ServiceConnectionData msgData = (ServiceConnectionData)msg.obj; 
                            // check that this isn't an old message
                            if (isSyncStillActive(msgData.activeSyncContext)) {
                                runBoundToSyncAdapter(msgData.activeSyncContext, msgData.syncAdapter);
                            }
                            break;
                        }
    

    runBoundToSyncAdapter会调用目标服务的startSync函数

            private void runBoundToSyncAdapter(final ActiveSyncContext activeSyncContext,
                  ISyncAdapter syncAdapter) {
                activeSyncContext.mSyncAdapter = syncAdapter;
                final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
                try {
                    activeSyncContext.mIsLinkedToDeath = true;
                    syncAdapter.asBinder().linkToDeath(activeSyncContext, 0);
    
                    syncAdapter.startSync(activeSyncContext, syncOperation.authority,
                            syncOperation.account, syncOperation.extras);
                } catch (RemoteException remoteExc) {
                    
                    closeActiveSyncContext(activeSyncContext);
                    increaseBackoffSetting(syncOperation);
                    scheduleSyncOperation(new SyncOperation(syncOperation));
                } catch (RuntimeException exc) {
                    closeActiveSyncContext(activeSyncContext);
                   
                }
            }
    
    

    3.3数据同步管理SyncManager总结

    TU 8-18

    recyclerview
    http://www.jianshu.com/p/2f2996ef2c75
    http://www.jianshu.com/p/6c78a5a07db5
    http://www.gcssloop.com/customview/matrix-3d-camera
    http://www.gcssloop.com/customview/CustomViewIndex
    http://blog.devwiki.net/index.php/2016/06/13/RecyclerView-Scroll-Listener.html
    http://mp.weixin.qq.com/s?__biz=MzI4MzE2MTQ5Mw==&mid=2649752111&idx=1&sn=414c62ff6c1485c9a7cd90dd3fc8f6e6#rd
    http://www.jianshu.com/p/411ab861034f
    http://blog.csdn.net/luoyanglizi/article/details/51519686
    http://blog.csdn.net/mynameishuangshuai/article/details/51153978
    http://blog.csdn.net/huachao1001/article/details/51594004
    http://www.jianshu.com/p/c82cebc4e798
    http://www.jianshu.com/p/b1ad50633732
    http://www.jianshu.com/p/d993ad653293
    http://www.jianshu.com/p/87a49f732724
    http://mouxuejie.com/blog/2016-03-06/recyclerview-analysis/
    http://mijack.github.io/2016/01/07/%E8%AE%A9%20Toolbar%20%E9%9A%8F%E7%9D%80%20RecyclerView%20%E7%9A%84%E6%BB%9A%E5%8A%A8%E8%80%8C%E6%98%BE%E7%A4%BA%E9%9A%90%E8%97%8F/
    http://kymjs.com/code/2015/11/26/01/
    http://android.jobbole.com/81947/
    https://github.com/nuptboyzhb/TreeRecyclerView
    http://www.jianshu.com/p/a92955be0a3e
    http://blog.csdn.net/u014099894/article/details/51855129
    https://github.com/zuiwuyuan/RecycleView_PullToRefresh_LoadMore
    http://blog.csdn.net/yanzhenjie1003/article/details/51935982
    https://github.com/songhanghang/Smart-HeaderFooter-RecyclerView
    http://blog.devwiki.net/index.php/2016/07/24/three-ways-click-recyclerview-item.html
    http://www.jianshu.com/p/a3388e716a93
    http://kymjs.com/code/2016/07/10/01
    https://github.com/oubowu/PinnedSectionItemDecoration/blob/master/README-CN.md
    http://blog.devwiki.net/index.php/2016/07/17/Recycler-View-Adapter-ViewHolder-optimized.html
    http://www.jianshu.com/p/12ec590f6c76
    https://github.com/dinuscxj/RecyclerItemDecoration
    https://segmentfault.com/a/1190000006147436
    https://github.com/dinuscxj/PullZoomRecyclerView
    http://loshine.me/2016/08/25/a-universal-solution-of-recyclerview-adapter-notify/
    http://blog.csdn.net/feiyangbahu1/article/details/52305769
    http://www.jianshu.com/p/f592f3715ae2
    http://blog.csdn.net/yanzhenjie1003/article/details/52115566
    http://www.jianshu.com/p/9bfed6e127cc
    https://github.com/CymChad/CymChad.github.io
    https://github.com/lufficc/LightAdapter
    https://github.com/markzhai/DataBindingAdapter
    http://www.jianshu.com/p/66c065874848
    http://blog.csdn.net/zxt0601/article/details/52420706
    http://blog.csdn.net/qifengdeqingchen/article/details/52388467
    https://github.com/kHRYSTAL/CircleRecyclerView
    http://hanhailong.com/2015/12/28/Android%E8%BF%9B%E9%98%B6%E4%B9%8BProGuard%E4%BB%A3%E7%A0%81%E6%B7%B7%E6%B7%86/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io
    http://blog.csdn.net/lmj623565791/article/details/46858663
    https://github.com/bboyfeiyu/android-tech-frontier/blob/master/issue-18/%E6%8B%96%E6%8B%BDRecyclerView.md
    http://androidone.io/info_10265.html
    https://github.com/cymcsg/UltimateRecyclerView
    http://www.itlanbao.com/code/20150812/10050/100317.html
    http://www.itlanbao.com/code/20150812/10050/100316.html
    http://www.itlanbao.com/code/20150812/10050/100322.html
    http://www.itlanbao.com/code/20150812/10050/100323.html
    http://www.itlanbao.com/code/20151111/10000/100639.html
    http://www.jianshu.com/p/a6f158d1a9c9

    相关文章

      网友评论

          本文标题:ContentService:第二部分数据同步

          本文链接:https://www.haomeiwen.com/subject/nvpoettx.html