调起同步有四种方式
1 ContentService.notifyChange()
2 requestSync
3 周期
4其他(如账号登陆,网络变化内存低变化等可能出发(一般都是之前发起的任务,没有网络或者内存低,没能执行))
对应的同步客户端设置:
android:accountType="com.letv" //账号类型
android:contentAuthority="com.provider.Wifi" //authority
android:allowParallelSyncs="false" //是否可以并行同步(目前最多两个任务并行)
android:supportsUploading="false" //是否支持notifyChange方式发起同步
android:isAlwaysSyncable="true" //是否一开始就是可同步的,如果不是要首先初始化后才能同步
android:userVisible="true"/> //用户是否可见,也就是在setting账号下面是否课件
对于上述1,2两种引起同步的方式,是客户端主动调用,都会走到
public void scheduleSync(Account requestedAccount, intuserId, intreason,
String requestedAuthority,Bundle extras, longbeforeRuntimeMillis,
longruntimeMillis, booleanonlyThoseWithUnkownSyncableState) {String requestedAuthority,Bundle extras, longbeforeRuntimeMillis,longruntimeMillis, booleanonlyThoseWithUnkownSyncableState) {
方法,这个方法的作用就是将同步任务添加到任务队列中,还有准备任务的一些参数和过滤一些无效请求,我们来看看任务是什么样子的
SyncOperation(account.account,account.userId,reason,source,
authority,extras,runtimeMillis,beforeRuntimeMillis,
backoffTime,delayUntil,allowParallelSyncs)
这个就是一个同步任务,添加到SyncQueue
中,其中构造函数的众多参数就是scheduleSync 需要准备的,
详细分析scheduleSync
函数
1过滤无效的账号
2过滤无效的authority
3 过滤无效的请求
这个过程中如果有需要初始化的authority会添加这样任务到队列中
任务添加到队列后(如果队列的内容发生变化,添加多队列的时候会和队列中的元素进行比较,看是否有比较添加该任务到队列)
发送MESSAGE_CHECK_ALARMS
异步消息
切换战场到handler中,消费者
private longmaybeStartNextSyncH() {
1 没有网络 存储控件低 设备休眠mRunningAccounts为null的时候直接返回
2 遍历队列,又检查一遍无效的请求,移除队列,idel的provider则增加回避时间
3 这里就要和正在运行的任务做一些比较,看看是取消正在运行的执行新的,还是其他策略如下
候选任务和一下几种任务比较
longRunning的:类型相同且运行时间超过五分钟的
oldestNonExpeditedRegular:不是加速的且运行时间最久的
conflict:冲突的
对于上述三种情况在某种情况需要重新调度,重新添加到调度队列
如果冲突的不为null
1 如果候选任务(肯定会被调度),是初始化任务,且正在执行的不是初始化任务,并且运行的初始化任务不超过上线,则设置 冲突的任务重新调度
2 如果候选任务是加速的,冲突任务不是加速的,并且两个任务类型一样,则设置冲突任务重新调度
3 如果候选任务是加速的,运行最久的任务不是加速的,,并且候选任务不是初始化的,则重新调度运行醉酒的
4 如果运行时间最长的任务不是 和候选者为同一类型 则重新调度运行时间超过五分钟的(一个)
然后bindservice, OnServiceConnect的时候调起同步
出现软错误的时候设置回退时间 硬错误或者同步成功的时候清除回退时间
关于回退时间的设置在
private voidincreaseBackoffSetting(SyncOperation op) {
函数中,我们来看看逻辑
第一次失败的时候回避时间为0,设置延迟时间为30-33秒之间的一个随机数,回避时间= 当前时间+延迟时间
以后随着软错误次数增加,回避延迟*2,最多不超过一个小时,
那么回避时间是啥呢? 是在添加任务到队列的时候会计算effectiveRunTime,如过这个时间-flexTime大于now的话,则该同步任务不会被执行,这个逻辑在longmaybeStartNextSyncH()函数中执行
就这样吧 然后解释下出现的几个时间
首先介绍
AuthorityInfo 下的三个时间:这个对应与一个同步项
backoffTime:回避时间(没有特殊设置,下次可以同步的时间)
backoffDelay:回避时间间隔,随错误次数翻倍,不超过1小时
delayUntil:用户设置 通过SyncResult返回
SyncOperation中的时间:
latestRunTime // 用于处理冲突,用户调用时候指定,一般是当前时间,或者notifyChange方式是30s
backoff //同AuthorityInfo.backoffTime
delayUntil 同AuthorityInfo.delayUntil
effectiveRunTime: 可以运行的时间 取值:max(max(latestRunTime,delayUntil),delayUntil)
flexTime 宽松时间effectiveRunTime-flexTime>now则不可以运行
所以本地数据库变化是三十秒可以运行