W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
編寫:kesenhoo - 原文:http://developer.android.com/training/efficient-downloads/regular_updates.html
最佳的定期更新頻率是不確定的,通常由設備狀態(tài),網(wǎng)絡連接狀態(tài),用戶行為與用戶顯式定義的偏好而決定。
Optimizing Battery Life這一章有討論如何根據(jù)主設備狀態(tài)來修改更新頻率,從而達到編寫一個低電量消耗的程序??蓤?zhí)行的操作包括當斷開網(wǎng)絡連接的時候去關閉后臺服務,在電量比較低的時候減少更新的頻率等。
這一課會介紹更新頻率是多少才會使得更新操作對無線電狀態(tài)機的影響最小。(C2DM與指數(shù)退避算法的使用)
每次 app 去向 server 詢問檢查是否有更新操作的時候,都會激活無線電,這樣造成了不必要的能量消耗(在3G情況下,會差不多消耗20秒的能量)。
Google Cloud Messaging for Android (GCM) 是一個用來從 server 到特定 app 傳輸數(shù)據(jù)的輕量級的機制。使用 GCM,server 會在某個 app 需要獲取新數(shù)據(jù)的時候通知 app 有這個消息。
比起輪詢方式(app 為了即時拿到最新的數(shù)據(jù)需要定時去ping server),GCM 這種由事件驅(qū)動的模式會在僅僅有數(shù)據(jù)更新的時候通知 app 去創(chuàng)建網(wǎng)絡連接來獲取數(shù)據(jù)(很顯然這樣減少了 app 的大量操作,當然也減少了很多電量消耗)。
GCM 需要通過使用持續(xù)的 TCP/IP 連接來實現(xiàn)操作。當我們可以實現(xiàn)自己的推送服務,最好使用 GCM(這個地方應該不是傳統(tǒng)意義上的固定IP,可以理解為某個會話情況下) 。很明顯,使用 GCM 既減少了網(wǎng)絡連接次數(shù),也優(yōu)化了帶寬,還減少了對電量的消耗。
PS:大陸的 Google 框架通常被移除掉,這導致 GCM 實際上根本沒有辦法在大陸的 App 上使用。
如果需要使用輪詢機制,在不影響用戶體驗的前提下,設置默認的更新頻率當然是越低越好(減少耗電量)。
一個簡單的方法是給用戶顯式修改更新頻率的選項,允許用戶自己來處理如何平衡數(shù)據(jù)及時性與電量的消耗。
當設置安排好更新操作后,可以使用不確定重復提醒的方式來允許系統(tǒng)把當前這個操作進行定向移動(比如推遲一會)。
int alarmType = AlarmManager.ELAPSED_REALTIME;
long interval = AlarmManager.INTERVAL_HOUR;
long start = System.currentTimeMillis() + interval;
alarmManager.setInexactRepeating(alarmType, start, interval, pi);
如果幾個提醒都安排在某個點同時被觸發(fā),那么就可以使得多個操作在同一個無線電狀態(tài)下操作完。
如果可以,請設置提醒的類型為 ELAPSED_REALTIME
或者 RTC
而不是 _WAKEUP
。通過一直等待知道手機在提醒通知觸發(fā)之前不再處于 standby 模式,進一步地減少電量的消耗。
我們還可以通過根據(jù)最近 app 被使用的頻率來有選擇性地減少更新的頻率,從而降低這些定期通知的影響。
另一個方法是在 app 在上一次更新操作之后還未被使用的情況下,使用指數(shù)退避算法 exponential back-off algorithm
來減少更新頻率。斷言一個最小的更新頻率和任何時候使用 app 都去重置頻率通常都是有用的方法。例如:
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();
初始化一個網(wǎng)絡連接的花費不會因為是否成功下載了數(shù)據(jù)而改變。對于那些成功完成是很重要的時間敏感的傳輸,我們可以使用指數(shù)退避算法來減少重復嘗試的次數(shù),這樣能夠避免浪費電量。例如:
private void retryIn(long interval) {
boolean success = attemptTransfer();
if (!success) {
retryIn(interval*2 < MAX_RETRY_INTERVAL ?
interval*2 : MAX_RETRY_INTERVAL);
}
}
另外,對于可以容忍失敗連接的傳輸(例如定期更新),我們可以簡單地忽略失敗的連接和傳輸嘗試。
筆者結(jié)語:這一課講到GCM與指數(shù)退避算法等,其實這些細節(jié)很值得我們注意,如果能在實際項目中加以應用,很明顯程序的質(zhì)量上升了一個檔次!
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: