Minimizing the Effect of Regular Updates[最小化定時更新操作的副作用]
- 最佳的定時更新頻率是不確定的,通常由設備狀態,網絡連接狀態,用戶行爲與用戶定義明確的偏好而決定。
- Optimizing Battery Life(【Android Training - 04】優化電池壽命)這一章有討論如何根據設備狀態來修改更新頻率。裏面介紹了當斷開網絡連接的時候去關閉後臺服務,在電量比較低的時候減少更新的頻率。
- 這一課會介紹更新頻率是多少纔會使得更新操作對無線電狀態機的影響最小。
- C2DM與指數退避算法的使用
Use Cloud to Device Messaging as an Alternative to Polling[使用C2DM作爲輪詢方式之一]
關於Android Cloud to Device Messaging (C2DM)詳情 ,請參考:http://code.google.com/intl/zh-CN/android/c2dm/- 每次app去向server詢問檢查是否有更新操作的時候會激活無線電,這樣造成了不必要的能量消耗(在3G情況下,會差不多消耗20秒的能量)。
- C2DM是一個用來從server到特定app傳輸數據的輕量級的機制。使用C2DM,server會在某個app有新數據的時候通知app有這個消息[有點像PUSH短信的類型]。
- 比起輪詢方式(app爲了即時拿到最新的數據需要定時向server請求數據),C2DM這種有事件驅動的模式會在僅僅有數據更新的時候通知app去創建網絡連接來獲取數據[很顯然這樣減少了app的大量操作,當然也減少了很多電量]。
- C2DM需要通過使用固定TCP/IP來實現操作。當在你的設備上可以實現固定IP的時候,最好使用C2DM。[這個地方應該不是傳統意義上的固定IP,可以理解爲某個會話情況下]。很明顯,使用C2DM既減少了網絡連接次數,也優化了帶寬,還減少了對電量的消耗。
Optimize Polling with Inexact Repeating Alarms and Exponential Backoffs[通過不定時的重複提醒與指數退避來優化輪詢操作]
- 如果需要使用輪詢機制,在不影響用戶體驗的前提下,當然設置默認更新頻率是越低越好[減少電量的浪費]。
- 一個簡單的方法是給用戶提供更新頻率的選擇,允許用戶自己來處理如何平衡數據及時性與電量的消耗。
- 當設置安排好更新操作後,可以使用不確定重複提醒的方式來允許系統把當前這個操作進行定向移動(比如推遲一會)。
- int alarmType = AlarmManager.ELAPSED_REALTIME;
- long interval = AlarmManager.INTERVAL_HOUR;
- long start = System.currentTimeMillis() + interval;
- alarmManager.setInexactRepeating(alarmType, start, interval, pi);
- 若是多個提醒都被做了“定向移動”,那麼很有可能到某個點同時被觸發,那麼這樣就可以使得多個操作在同一個無線電狀態下操作完。
- 如果可以,請設置提醒的類型爲ELAPSED_REALTIME or RTC而不是_WAKEUP。這樣能夠更進一步的減少在等待同時被觸發的時候對電量的消耗。
- 我們還可以通過根據app被使用的頻率來有選擇性的減少更新的頻率。
- 另一個方法在app在上一次更新操作之後還未被使用的情況下,使用指數退避算法(exponential back-off algorithm)來減少更新頻率。當然我們也可以使用一些類似指數退避的方法。
- SharedPreferences sp =
- context.getSharedPreferences(PREFS, Context.MODE_WORLD_READABLE);
- boolean appUsed = sp.getBoolean(PREFS_APPUSED, false);
- long updateInterval = sp.getLong(PREFS_INTERVAL, DEFAULT_REFRESH_INTERVAL);
- if (!appUsed)
- if ((updateInterval *= 2) > MAX_REFRESH_INTERVAL)
- updateInterval = MAX_REFRESH_INTERVAL;
- Editor spEdit = sp.edit();
- spEdit.putBoolean(PREFS_APPUSED, false);
- spEdit.putLong(PREFS_INTERVAL, updateInterval);
- spEdit.apply();
- rescheduleUpdates(updateInterval);
- executeUpdateOrPrefetch();
- 初始化一個網絡連接的花費不會因爲是否成功下載了數據而改變。我們可以使用指數退避算法來減少重複嘗試(retry)的次數,這樣能夠避免浪費電量。例如:
- private void retryIn(long interval) {
- boolean success = attemptTransfer();
- if (!success) {
- retryIn(interval*2 < MAX_RETRY_INTERVAL ?
- interval*2 : MAX_RETRY_INTERVAL);
- }
- }
後記:這一課講到C2DM與指數退避算法等,其實這些細節很值得我們注意,如果能在實際項目中加以應用,很明顯質量會比較高。謝謝!