<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ContentResolver提供了一個requestSync函數,用于發起一次數據同步請求。在本例中,該函數的調用方法如下: ~~~ Account emailSyncAccount = newAccount("fanping.deng@gmail", "com.google"); String emailAuthority ="com.android.email.provider"; Bundle emailBundle = new Bundle(); ......//為emailBundle添加相關的參數。這些內容和具體的同步服務有關 //發起Email同步請求 ContentResolver.requesetSync(emailSyncAccount,emailAuthority,emailBundle); ~~~ 1. 客戶端發起請求 ContentResolver requestSync的代碼如下: **ContentResolver.java::requestSync** ~~~ public static void requestSync(Account account,String authority, Bundle extras) { //檢查extras攜帶的參數的數據類型,目前只支持float、int和String等幾種類型 validateSyncExtrasBundle(extras); try { //調用ContentService的requestSync函數 getContentService().requestSync(account, authority, extras); }...... } ~~~ 與添加賬戶(addAccount)相比,客戶端發起一次同步請求所要做的工作就太簡單了。 下面轉戰ContentService去看它的requestSync函數。 2. ContentService 的requestSync函數分析 **ContentService.java::requestSync** ~~~ public void requestSync(Account account, Stringauthority, Bundle extras) { ContentResolver.validateSyncExtrasBundle(extras); longidentityToken = clearCallingIdentity(); try { SyncManager syncManager = getSyncManager(); if(syncManager != null) { //調用syncManager的scheduleSync syncManager.scheduleSync(account, authority, extras, 0,false); } }finally { restoreCallingIdentity(identityToken); } } ~~~ ContentService將工作轉交給SyncManager來完成,其調用的函數是scheduleSync。 (1) SyncManager的scheduleSync函數分析 先行介紹的scheduleSync函數非常重要。 ~~~ /* scheduleSync一共5個參數,其作用分別如下。 requestedAccount表明要進行同步操作的賬戶。如果為空,SyncManager將同步所有賬戶。 requestedAuthority表明要同步的數據項。如果為空,SyncManager將同步所有數據項。 extras指定同步操作中的一些參數信息。這部分內容后續分析時再來介紹。 delay指定本次同步請求是否延遲執行。單位為毫秒。 onlyThoseWithUnkownSyncableState是否只同步那些處于unknown狀態的同步服務。該參數 在代碼中沒有注釋。結合前面對syncable為unknown的分析,如果該參數為true,則 本次同步請求的主要作用就是通知同步服務進行初始化操作 */ public void scheduleSync(Account requestedAccount,String requestedAuthority, Bundleextras, long delay,boolean onlyThoseWithUnkownSyncableState) ~~~ 關于scheduleSync的代碼將分段分析,其相關代碼如下: **SyncManager.java::scheduleSync** ~~~ boopublic void scheduleSync(AccountrequestedAccount, StringrequestedAuthority, Bundle extras, long delay, boolean onlyThoseWithUnkownSyncableState) //判斷是否允許后臺數據傳輸 finalboolean backgroundDataUsageAllowed = !mBootCompleted || getConnectivityManager().getBackgroundDataSetting(); if (extras== null) extras = new Bundle(); //下面將解析同步服務中特有的一些參數信息,下面將逐條解釋 //SYNC_EXTRAS_EXPEDITED參數表示是否立即執行。如果設置了該選項,則delay參數不起作用 //delay參數用于設置延遲執行時間,單位為毫秒 Booleanexpedited = extras.getBoolean( ContentResolver.SYNC_EXTRAS_EXPEDITED,false); if (expedited) delay = -1; Account[]accounts; if (requestedAccount != null) { accounts = new Account[]{requestedAccount}; } ...... //SYNC_EXTRAS_UPLOAD參數設置本次同步是否對應為上傳。從本地同步到服務端為Upload, //反之為download finalboolean uploadOnly = extras.getBoolean( ContentResolver.SYNC_EXTRAS_UPLOAD, false); //SYNC_EXTRAS_MANUAL等同于SYNC_EXTRAS_IGNORE_BACKOFF加 //SYNC_EXTRAS_IGNORE_SETTINGS final boolean manualSync = extras.getBoolean( ContentResolver.SYNC_EXTRAS_MANUAL, false); //如果是手動同步,則忽略backoff和settings參數的影響 if(manualSync) { //知識點一:SYNC_EXTRAS_IGNORE_BACKOFF:該參數和backoff有關,見下文的解釋 extras.putBoolean( ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true); //SYNC_EXTRAS_IGNORE_SETTINGS:忽略設置 extras.putBoolean( ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true); } finalboolean 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 { source = SyncStorageEngine.SOURCE_SERVER; } ~~~ 在以上代碼中,有兩個知識點需要說明。 知識點一和backoff有關:這個詞不太好翻譯。和其相關的應用場景是,如果本次同步操作執行失敗,則嘗試休息一會再執行,而backoff在這個場景中的作用就是控制休息時間。由以上代碼可知,當用戶設置了手動(Manual)參數后,就無須對這次同步操作使用backoff模式。 另外,在后續的代碼中,我們會發現和backoff有關的數據被定義成一個Paire<Long,Long>,即backoff對應兩個參數。這兩個參數到底有什么用呢?筆者在SyncManager代碼中找到了一個函數,其參數的命名很容易理解。該函數是setBackoff,原型如下: **SyncManager.java::setBackoff** ~~~ public void setBackoff(Account account, StringproviderName, long nextSyncTime, long nextDelay) ~~~ 在調用這個函數時,Pair<Long,Long>中的兩個參數分別對應nextSyncTime和nextDelay,所以,Pair中的第一個參數對應nextSyncTime,第二個參數對應nextDelay。backoff的計算中實際上存在著一種算法。它是什么呢?讀者不妨先研究setBackoff,然后再和我們一起分享。 知識點二和SyncStorageEngine定義的觸發源有關。說白了,觸發源就是描述該次同步操作是因何而起的。SyncStorageEngine一共定義了4種類型的源,這里筆者直接展示其原文解釋: ~~~ /* Enumvalue for a local-initiated sync. */ public static final int SOURCE_LOCAL = 1; /** Enum value for a poll-based sync (e.g., upon connectionto network)*/ public static final int SOURCE_POLL = 2; /* Enumvalue for a user-initiated sync. */ public static final int SOURCE_USER = 3; /* Enumvalue for a periodic sync. */ publicstatic final int SOURCE_PERIODIC = 4; ~~~ 觸發源的作用主要是為了SyncStorageEngine的統計工作。本節不打算深究這部分內容,感興趣的讀者可在學習完本節后自行研究。 關于scheduleSync下一階段的工作,代碼如下: **SyncManager.java::scheduleSync** ~~~ //從SyncAdaptersCache中取出所有SyncService信息 final HashSet<String>syncableAuthorities = new HashSet<String>(); for(RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter :mSyncAdapters.getAllServices()) { syncableAuthorities.add(syncAdapter.type.authority); } //如果指定了本次同步的authority,則從上述同步服務信息中找到滿足要求的SyncService if(requestedAuthority != null) { final boolean hasSyncAdapter = syncableAuthorities.contains(requestedAuthority); syncableAuthorities.clear(); if(hasSyncAdapter) syncableAuthorities.add(requestedAuthority); } finalboolean masterSyncAutomatically = mSyncStorageEngine.getMasterSyncAutomatically(); for(String authority : syncableAuthorities) { for(Account account : accounts) { //取出AuthorityInfo中的syncable狀態,如果為1,則syncable為true, //如果為-1,則狀態為unknown intisSyncable = mSyncStorageEngine.getIsSyncable( account,authority); if(isSyncable == 0) continue;//syncable為false,則不能進行同步操作 final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo = mSyncAdapters.getServiceInfo( SyncAdapterType.newKey(authority, account.type)); ...... //有些同步服務支持多路并發同步操作 final boolean allowParallelSyncs = syncAdapterInfo.type.allowParallelSyncs(); finalboolean isAlwaysSyncable = syncAdapterInfo.type. isAlwaysSyncable(); //如果該同步服務此時的狀態為unknown,而它又是永遠可同步的(AlwaysSyncable), //那么通過setIsSyncable設置該服務的狀態為1 if(isSyncable < 0 && isAlwaysSyncable) { mSyncStorageEngine.setIsSyncable(account, authority, 1); isSyncable = 1; } //如果只操作unknow狀態的同步服務,并且該服務的狀態不是unknown,則不允許后續操作 if(onlyThoseWithUnkownSyncableState && isSyncable >= 0) continue; //如果此同步服務不支持上傳,而本次同步又需要上傳,則不允許后續操作 if(!syncAdapterInfo.type.supportsUploading() && uploadOnly) continue; //判斷是否允許執行本次同步操作。如果同步服務狀態為unknown,則總是允許發起同步請求, //因為這時的同步請求只是為了初始化SyncService boolean syncAllowed = (isSyncable < 0) ||ignoreSettings || (backgroundDataUsageAllowed && masterSyncAutomatically && mSyncStorageEngine.getSyncAutomatically( account,authority)); ...... //取出對應的backoff參數 Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff( account,authority); //獲取延遲執行時間 longdelayUntil = mSyncStorageEngine.getDelayUntilTime( account,authority); finallong backoffTime = backoff != null ? backoff.first : 0; if(isSyncable < 0) { Bundle newExtras = new Bundle(); //如果syncable狀態為unknown,則需要設置一個特殊的參數,即 //SYNC_EXTRAS_INITIALIZE,它將通知SyncService進行初始化操作 newExtras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true); scheduleSyncOperation( new SyncOperation(account, source, authority, newExtras, 0, backoffTime,delayUntil,allowParallelSyncs)); } if(!onlyThoseWithUnkownSyncableState) scheduleSyncOperation( new SyncOperation(account,source, authority, extras, delay, backoffTime, delayUntil,allowParallelSyncs)); }//for循環結束 } } ~~~ scheduleSync函數較復雜,難點在于其策略控制。建議讀者反復閱讀這部分內容。 scheduleSync最后將構造一個SyncOperation對象,并調用scheduleSyncOperation處理它。scheduleSyncOperation內部會將這個SyncOperation對象保存到mSyncQueue中,然后發送MESSAGE_CHECK_ALARMS消息讓mSyncHandler去處理。由于scheduleSyncOperation函數比較簡單,因此下面將直接去mSyncHandler的handleMessage函數中分析MESSAGE_CHECK_ALARMS的處理過程。 (2) 處理MESSAGE_CHECK_ALARMS消息 SyncHandler的handleMessage代碼如下: **SyncManager.java::SyncHandler:handleMessage** ~~~ public void handleMessage(Message msg) { longearliestFuturePollTime = Long.MAX_VALUE; longnextPendingSyncTime = Long.MAX_VALUE; try { waitUntilReadyToRun(); mDataConnectionIsConnected = readDataConnectionState(); //獲得WakeLock,防止在同步過程中掉電 mSyncManagerWakeLock.acquire(); //處理周期同步的操作 earliestFuturePollTime= scheduleReadyPeriodicSyncs(); switch (msg.what) { ...... case SyncHandler.MESSAGE_CHECK_ALARMS: //調用maybeStartNextSyncLocked函數,返回一個時間。見下文解釋 nextPendingSyncTime = maybeStartNextSyncLocked(); break; ...... }//switch結束 } finally{ manageSyncNotificationLocked(); /* 將上邊函數調用的返回值傳遞給manageSyncAlarmLocked,該函數內部與 AlarmManagerService交互,其實就是定義一個定時提醒。在Alarm超時后,就會廣播 在SyncManager構造函數中定義的那個PendingIntent mSyncAlarmIntent, 而SyncManager收到該廣播后又會做對應處理。相關內容讀者可自行閱讀 */ manageSyncAlarmLocked(earliestFuturePollTime,nextPendingSyncTime); mSyncTimeTracker.update(); mSyncManagerWakeLock.release(); } } ~~~ 如以上代碼所述,MESSAGE_CHECK_ALARMS消息的處理就是調用maybeStartNextSyncLocked函數。這個函數內容較繁瑣,它主要做了以下幾項工作。 - 檢查SyncQueue中保存的同步操作對象SyncOperation,判斷它們對應的同步服務的狀態是否為false,如果為false,則不允許執行該同步操作。 - 查詢ConnectivityManagerService以判斷目標同步服務是否使用了網絡。如果該服務當前沒有使用網絡,則不允許執行該同步操作。 - 判斷同步操作對象的執行時間是否已到,如果未到,則不允許執行該操作。 - 將通過上述判斷的同步操作對象SyncOperation與當前系統中正在執行的同步操作上下文對象進行比較。系統當前正在執行的同步操作上下文對象對應的數據類是ActiveSyncContext,它是在同步操作對象之上的一個封裝,包含了能和同步服務交互的接口。由于并非所有同步服務都支持多路并發同步操作,因此這里需做一些處理,以避免不必要的同步操作。另外,如一個僅對應初始化同步服務的同步操作執行時間過長(由系統屬性“sync.max_time_per_sync”控制,默認是5分鐘),系統也需做一些處理。 * * * * * **提示**:maybeStartNextSyncLocked是筆者在本節留給讀者自行分析的函數中最難的一個。讀者務必閱讀完下面的分析后,嘗試去研究此函數。 * * * * * 通過上述層層考驗后,manageSyncAlarmLocked最后將調用dispatchSyncOperation真正去派發一個同步操作。下面來看dispatchSyncOperation的代碼。 **SyncManager.java::dispatchSyncOperation** ~~~ private booleandispatchSyncOperation(SyncOperation op) { SyncAdapterType syncAdapterType = SyncAdapterType. newKey(op.authority,op.account.type); RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo= mSyncAdapters.getServiceInfo(syncAdapterType); ...... //構造一個ActiveSyncContext對象,它就是前面提到的同步操作上下文對象 ActiveSyncContextactiveSyncContext = new ActiveSyncContext(op, insertStartSyncEvent(op), syncAdapterInfo.uid); activeSyncContext.mSyncInfo = mSyncStorageEngine.addActiveSync(activeSyncContext); // mActiveSyncContexts保存了當前系統中所有的ActiveSyncContext對象 mActiveSyncContexts.add(activeSyncContext); //為該對象綁定到具體的同步服務上 if(!activeSyncContext.bindToSyncAdapter(syncAdapterInfo)) { closeActiveSyncContext(activeSyncContext); return false; } returntrue; } ~~~ ActiveSyncContext是SyncManager和同步服務交互的關鍵類,其家族圖譜如圖8-16所示。 :-: ![](http://img.blog.csdn.net/20150803131747220?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-16 ActiveSyncContext的 UML類圖 圖8-16中的ActiveSyncContext和圖8-8中的Session非常像。ActiveSyncContext的主要工作包括下面兩部分。 - 它將首先通過bindService方式啟動SyncService,并在onServiceConnected函數中得到用于和SyncService交互的接口對象,即參與Binder通信的ISyncAdapterBp端。 - ActiveSyncContext是ISyncContext接口的Binder通信的Bn端,它在調用ISyncAdapter的startSync時,會把自己傳遞給同步服務。同步服務得到的當然是ISyncContext的Bp端對象。當同步服務完成此次同步操作后就會調用ISyncContext 的Bp端對象的onFinished函數以通知ActiveSyncContext同步操作的執行結果。 下面再看第一部分的工作。 (3) ActiveSyncContext派發請求 **SyncManager.java::ActiveSyncContext.bindToSyncAdapter** ~~~ booleanbindToSyncAdapter(RegisteredServicesCache.ServiceInfo info) { Intentintent = 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.getActivity( mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS),0)); mBound= true; //調用bindService啟動指定的同步服務 finalboolean bindResult = mContext.bindService(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT); if(!bindResult) mBound = false; returnbindResult; } ~~~ 當目標SyncService從其onBind函數返回后,ActiveSyncContext的onServiceConnected將被調用,該函數的內部處理流程如下: **SyncManager.java::ActiveSyncContext.onServiceConnected** ~~~ public void onServiceConnected(ComponentName name,IBinder service) { Messagemsg = mSyncHandler.obtainMessage(); msg.what= SyncHandler.MESSAGE_SERVICE_CONNECTED; //構造一個ServiceConnectionData對象,并發送MESSAGE_SERVICE_CONNECTED消息 //給mSyncHandler。第二個參數就是SyncService在onBind函數中返回的ISyncAdapter的 //Binder通信對象。不過在ActiveSyncContext中,它是Bp端 msg.obj= new ServiceConnectionData(this, ISyncAdapter.Stub.asInterface(service)); mSyncHandler.sendMessage(msg); } ~~~ **SyncManager.java::SyncHandler.handleMessage** ~~~ case SyncHandler.MESSAGE_SERVICE_CONNECTED: { ServiceConnectionData msgData = (ServiceConnectionData)msg.obj; if(isSyncStillActive(msgData.activeSyncContext)) //調用runBoundToSyncAdapter函數處理 runBoundToSyncAdapter(msgData.activeSyncContext, msgData.syncAdapter); break; } ~~~ **SyncManager.java::runBoundToSyncAdapter** ~~~ private void runBoundToSyncAdapter(final ActiveSyncContextactiveSyncContext, ISyncAdapter syncAdapter) { activeSyncContext.mSyncAdapter = syncAdapter; finalSyncOperation syncOperation = activeSyncContext.mSyncOperation; try { activeSyncContext.mIsLinkedToDeath = true; syncAdapter.asBinder().linkToDeath(activeSyncContext, 0); //調用目標同步服務的startSync函數 syncAdapter.startSync(activeSyncContext, syncOperation.authority, syncOperation.account, syncOperation.extras); } ...... } ~~~ 對SynManager工作的分析到此為止,下面將分析目標同步服務。 3. EmailSyncAdapterService處理請求 在本例中,目標同步服務位于EmailSyncAdapterService中,先看它通過onBind函數返回給ActiveSyncContext的是什么。 (1) onBind分析 **EmailSyncAdapterService.java::onBind** ~~~ public IBinder onBind(Intent intent) { //sSyncAdapter是EmailSyncAdapterService的內部類對象,見下文解釋 returnsSyncAdapter.getSyncAdapterBinder(); } ~~~ 在以上代碼中,sSyncAdapter的類型是EmailSyncAdapterService中的內部類SyncAdapterImpl。它的派生關系如圖8-17所示。 :-: ![](http://img.blog.csdn.net/20150803131801930?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-17 SyncAdapterImpl派生關系圖 有圖8-17可知: - AbstractThreadSyncAdapter是核心類,其內部有一個成員變量mISyncAdapterIml,該變量用于和ActiveSyncContext交互,是ISyncAdapter Binder通信的Bn端。該對象也是以上代碼中onBind函數的返回值。 - SyncThread從Thread派生。從這一點可看出,同步服務將創建工作線程來執行具體的同步操作。AbstractThreadSyncAdapter中的mSyncThreads保存該同步服務中所有的SyncThread對象。 - 同步操作的結果將通過SyncResult返給SyncManager。 再看SyncManager runBoundToSyncAdapter函數最后調用的startSync函數。 (2) startSync分析 在SyncService中,首先被調用的函數是ISyncAdapterImpl的startSync函數,其代碼為: **AbstractThreadedSyncAdapter.java::ISyncAdapterImpl.startSync** ~~~ public void startSync(ISyncContext syncContext,String authority, Account account,Bundle extras) { //構造一個SyncContext對象,用于保存上下文信息 finalSyncContext syncContextClient = new SyncContext(syncContext); booleanalreadyInProgress; finalAccount threadsKey = toSyncKey(account); synchronized (mSyncThreadLock) { //判斷是否存在已經在執行的SyncThread if(!mSyncThreads.containsKey(threadsKey)) { if (mAutoInitialize && extras != null&& extras.getBoolean( ContentResolver.SYNC_EXTRAS_INITIALIZE, false)) { //一般而言,mAutoInitialize都為true,表示同步服務支持自動初始化 //如果該服務對應的syncable狀態為unknown,則重新設置syncable為1 if (ContentResolver.getIsSyncable(account, authority) < 0) ContentResolver.setIsSyncable(account,authority, 1); //直接返回,不再做后續的處理,實際上后續的流程是可以繼續進行的 syncContextClient.onFinished(new SyncResult()); return; } //創建一個新的SyncThread對象 SyncThread syncThread = new SyncThread( "SyncAdapterThread-" + mNumSyncStarts.incrementAndGet(), syncContextClient,authority, account, extras); mSyncThreads.put(threadsKey, syncThread); syncThread.start();//啟動工作線程 alreadyInProgress = false; }else { alreadyInProgress = true; } } if(alreadyInProgress) syncContextClient.onFinished(SyncResult.ALREADY_IN_PROGRESS); } ~~~ 假如尚未匹配的工作線程(根據account生成一個key作為標示來查找是否已經存在對應的工作線程),SyncService將創建一個SyncThread,其run函數代碼是: **AbstractThreadedSyncAdapter.java::ISyncAdapterImpl.run** ~~~ public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); SyncResult syncResult = new SyncResult(); ContentProviderClient provider = null; try { if(isCanceled()) return; //獲得同步操作指定的ContentProvider,provider是ContentProviderClient //類型,用于和目標ContentProvider交互 provider = mContext.getContentResolver(). acquireContentProviderClient(mAuthority); if (provider != null) { //調用AbstractThreadedSyncAdapter子類的onPerformSync函數 AbstractThreadedSyncAdapter.this.onPerformSync(mAccount, mExtras,mAuthority,provider, syncResult); } else syncResult.databaseError = true; }finally { if (provider != null) provider.release(); if (!isCanceled()) //通知結果 mSyncContext.onFinished(syncResult); //工作完成,將該線程從mSyncThreads中移除 synchronized (mSyncThreadLock) { mSyncThreads.remove(mThreadsKey); } } } ~~~ 來看AbstractThreadedSyncAdapter子類實現的onPeroformSync函數,在本例中,子類是SyncAdapterImpl,代碼如下: **EmailSyncAdapterService.java::SyncAdapterImpl.onPerformSync** ~~~ public void onPerformSync(Account account, Bundleextras, String authority, ContentProviderClient provider,SyncResult syncResult) { try { //調用EmailSyncAdapterService performSync完成真正的同步,這部分代碼和 //Email業務邏輯相關,此處不再深入研究 EmailSyncAdapterService.performSync(mContext, account, extras, authority, provider,syncResult); }...... } ~~~ 執行完onPerformSync函數后,ISyncAdapterImpl.run返回前會調用mSyncContext.onFinished函數,向位于SyncManager中的ActiveSyncContext通知同步操作的結果。讀者可自行研究這部分內容。 4. ContentResolver requestSync分析總結 總結requestSync的工作流程,如圖8-18所示。 :-: ![](http://img.blog.csdn.net/20150803131817211?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-18 requestSync流程 由圖8-18可知,requestSync涉及的對象及調用流程比較繁瑣。但從技術上看,則沒有什么需要特別注意的地方。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看