Android省電開發(fā)

被問到啊哈哈哈,宛如一個(gè)智障的我為什么沒有想到在验!
性能優(yōu)化肯定會省電啊啊啊
其他的沒說,這個(gè)怎么……

憋說了堵未,來來來腋舌,整理一波

轉(zhuǎn)載自享受技術(shù)帶來的快樂

(一)性能優(yōu)化

Android開發(fā)除了NDK之外,使用的都是Java語言渗蟹,而Java語言是一種基于虛擬機(jī)JVM運(yùn)行的語言块饺,所以相比C/C++語言來說,效率是比較低的雌芽。Java需要占用大量內(nèi)存來換取執(zhí)行速度授艰,而不定期的GC機(jī)制,直接導(dǎo)致Android界面的卡頓現(xiàn)象世落。

Java語言優(yōu)化

1. 使用非阻塞I/O

版本較低的JDK不支持非阻塞I/O API淮腾。為了避免I/O阻塞,一些應(yīng)用采用了創(chuàng)建大量線程的方法(在較好的情況下屉佳,會使用一個(gè)緩沖池)谷朝。這種技術(shù)可以在許多必須支持并發(fā)I/O流的應(yīng)用中見到,如web服務(wù)器等武花。然而圆凰,創(chuàng)建Java線程需要相當(dāng)可觀的開銷。Java在JDK 1.4及以后版本中提供了一套API來專門操作非阻塞I/O体箕,我們可以再java.nio包及其子包中找到相關(guān)的類和接口专钉。由于這套API是JDK新提供的I/O API,因此累铅,也叫New I/O跃须,這就是包名nio的由來。這套API由3個(gè)主要的部分組成:緩沖區(qū)(Buffers)娃兽、通道(Channels)和非阻塞I/O的核心類回怜。

2. 慎用異常

異常對性能不利。拋出異常首先要?jiǎng)?chuàng)建一個(gè)新的對象换薄。 Throwable 接口的構(gòu)造函數(shù)調(diào)用名為 fillnStackTrace()的本地(Native)方法玉雾,fillnStackTrace() 方法檢查堆棧,收集調(diào)用跟蹤信息轻要。只要有異常被拋出复旬,VM就必須調(diào)整調(diào)用堆棧,因?yàn)樵谔幚磉^程中創(chuàng)建了一個(gè)新的對象冲泥。異常只能用于錯(cuò)誤處理驹碍,不應(yīng)該用來控制程序流程壁涎。

3. 變量和修飾符

  • 不要重復(fù)初始化變量。默認(rèn)情況下志秃,調(diào)用類的構(gòu)造函數(shù)時(shí)怔球,Java會把變量初始化成確定的值:所有的對象被設(shè)置成null,整數(shù)變量(byte浮还、short竟坛、int、long)設(shè)置成0钧舌,float和double設(shè)置成0.0担汤,邏輯值設(shè)置成false。所有盡量不要重復(fù)初始化變量洼冻。

  • 盡量使用局部變量崭歧,調(diào)用方法時(shí)傳遞的參數(shù)以及在調(diào)用中創(chuàng)建的臨時(shí)變量都保存在棧(stack)中,速度較快撞牢,并且隨所在線程的死亡而自動(dòng)銷毀率碾。其他變量,如靜態(tài)變量屋彪、實(shí)例變量等所宰,都在堆(heap)中創(chuàng)建,速度較慢撼班,垃圾回收是的耗能會導(dǎo)致APP出現(xiàn)卡頓現(xiàn)象歧匈。

  • 盡量指定類的final修飾符垒酬。帶有final修飾符的類是不可派生的砰嘁。另外,如果指定一個(gè)類為final勘究,則該類所有的方法都是final矮湘。Java編譯器會尋找機(jī)會內(nèi)聯(lián)(inline)所有的final方法。此舉能夠使性能平均提高50%口糕。

  • 私有內(nèi)部類要訪問外部類的field或方法時(shí)缅阳,其成員變量不要用private,因?yàn)樵诰幾g時(shí)會生成setter/getter影響性能景描∈欤可以把外部類的field或者方法聲明為包訪問權(quán)限。

  • 如果方法用不到成員變量超棺,可以把方法申明為static向族,性能會提高到15%到20%。

4. 其他方面:

  • 用位操作代替乘除法棠绘;
  • 用StringBuilder代替拼接操作件相;
  • 對算法進(jìn)行復(fù)雜度的改進(jìn)(必要的時(shí)候可以空間換時(shí)間)再扭;
  • 合理利用浮點(diǎn)數(shù),浮點(diǎn)數(shù)比整形慢兩倍夜矗。
  • 網(wǎng)絡(luò)優(yōu)化泛范、異步線程、圖片使用緩存等紊撕。

UI布局優(yōu)化

  • 1.布局層數(shù)盡量少罢荡,RelativeLayout來代替LinearLayout,因?yàn)镽elativeLayout性能更優(yōu)逛揩,且可以簡單實(shí)現(xiàn)LinearLayout嵌套才能實(shí)現(xiàn)的布局柠傍。

  • 2.采用<merge>標(biāo)簽優(yōu)化合并布局層數(shù):系統(tǒng)在編譯XML布局文件時(shí)不會為<merge>生成任何節(jié)點(diǎn),通過合并可以大大減少標(biāo)簽的生成辩稽。

  • 3.采用<include>標(biāo)簽共享重用其他布局:并用android:id屬性覆蓋被引用布局文件中頂層節(jié)點(diǎn)的android:id屬性值惧笛。

<!—引用mylayout.xml文件>  
<include android:id=”@+id/layout1” layout=”@layout/mylayout”/>  
    1. <viewstub> 標(biāo)簽:viewstub標(biāo)簽同include標(biāo)簽一樣可以用來引入一個(gè)外部布局,不同的是逞泄,viewstub引入的布局默認(rèn)不會擴(kuò)張患整,即既不會占用顯示也不會占用位置,從而在解析layout時(shí)節(jié)省cpu和內(nèi)存喷众。 <viewstub> 常用來引入那些默認(rèn)不會顯示各谚,只在特殊情況下顯示的布局,如進(jìn)度布局到千、網(wǎng)絡(luò)失敗顯示的刷新布局昌渤、信息出錯(cuò)出現(xiàn)的提示布局等。
  • 5.通過Android SDK中tools目錄下的 layoutopt 命令查看你的布局是否需要優(yōu)化憔四。

  • 6.將Activity中的window的背景圖設(shè)置為空膀息。 .getWindow().setBackgroundDrawable(null) ;android默認(rèn)的背景不為空了赵。

  • 7.View中設(shè)置緩存屬性 lsetDrawingCache l為true潜支。動(dòng)態(tài)加載View時(shí)采用ViewStub避免一些不經(jīng)常的視圖長期握住引用。

  • 8.采用SurfaceView在子線程刷新UI柿汛,避免手勢的處理和繪制在同一UI線程(普通View都這樣做)冗酿。

  • 9.ListView的優(yōu)化

    • item盡可能的減少使用的控件和布局的層次;
    • RelativeLayout是絕對的利器络断,通過它可以減少布局的層次裁替。
    • 盡可能的復(fù)用控件,這樣可以減少 ListView的內(nèi)存使用貌笨,減少滑動(dòng)時(shí)GC次數(shù)弱判。
    • ListView的背景色與cacheColorHint設(shè)置相同顏色,可以提高滑動(dòng)時(shí)的渲染性能躁绸。
    • ListView中g(shù)etView是性能是關(guān)鍵裕循,這里要盡可能的優(yōu)化臣嚣。
    • getView方法中要重用view;
    • getView方法中不能做復(fù)雜的邏輯計(jì)算剥哑, 特別是數(shù)據(jù)庫操作硅则,否則會嚴(yán)重影響滑動(dòng)時(shí)的性能。

數(shù)據(jù)庫優(yōu)化

  1. 有些能用文件操作的株婴,盡量使用文件操作怎虫,文件操作的速度比數(shù)據(jù)庫的操作要快10倍左右。

  2. Cursor的使用困介,管理好cursor大审,不要每次打開關(guān)閉cursor,因?yàn)榇蜷_關(guān)閉cursor非常耗時(shí)座哩。Cursor.require用于刷cursor徒扶。同時(shí)由于SQLiteDatabase對象較為耗費(fèi)資源,所以我們在使用完SQLiteDatabase對象之后根穷,必須立即關(guān)閉它姜骡,避免它繼續(xù)占用資源,否則我們繼續(xù)程序可能會導(dǎo)致OOM或者其他異常屿良。

  3. SQLite使用事務(wù),也可以自定義事務(wù)圈澈。使用事務(wù)好處是原子提交和更優(yōu)性能。

Db.beginTransaction();  
Db.setTransactionSuccessful();  
Db.end Transaction();  
  1. 可以建立索引尘惧,增加檢索的速度康栈。(當(dāng)某字段數(shù)據(jù)更新頻率較低,查詢頻率較高喷橙,經(jīng)常有范圍查詢(>,<, =, >=, <=)或orderby啥么、group by發(fā)生時(shí)建議使用索引; 經(jīng)常同時(shí)存取多列重慢,且每列都含有重復(fù)值可考慮建立復(fù)合索引)饥臂。

  2. 批量插入逊躁、更新使用原子操作似踱,采用事務(wù)等方式。

  3. 查詢時(shí)返回更少的結(jié)果集及更少的字段稽煤。

  4. 少用cursor.getColumnIndex(可以在建表的時(shí)候用static變量記住某列的index核芽,直接調(diào)用相應(yīng)index而不是每次查詢。)

  5. 優(yōu)化sql語句字符串等酵熙,語句的拼接使用StringBuilder代替String轧简。


新機(jī)制或者借用工具

  • 采用JNI技術(shù),將耗時(shí)間的處理放到c/c++層處理匾二。適當(dāng)?shù)牟捎肗DK編程可以提高效率哮独,但是內(nèi)存回收不穩(wěn)定拳芙,所以說適當(dāng)。
  1. 懶加載和緩存機(jī)制:訪問網(wǎng)絡(luò)的耗時(shí)操作啟動(dòng)一個(gè)新線程來做皮璧,而不要在UI線程做舟扎。還有從網(wǎng)絡(luò)上獲取大量圖片的時(shí)候,可以本地緩存悴务,下次獲取同樣圖片的時(shí)候睹限,可以先從本地獲取,本地?zé)o再從網(wǎng)絡(luò)獲取讯檐。

  2. 通過Android SDK中tools目錄下的layoutopt命令查看你的布局是否需要優(yōu)化羡疗;hierarchy viewer可以方便的查看Activity的布局,各個(gè)View的屬性别洪、measure叨恨、layout、draw的時(shí)間挖垛,如果耗時(shí)較多會用紅色標(biāo)記特碳,否則顯示綠色;利用android自帶的性能跟蹤工具TraceView查看跟蹤函數(shù)調(diào)用晕换,跟蹤方法跟蹤各部分的執(zhí)行效率午乓。

  3. 可以在方法執(zhí)行前后各使用system.currentTimeMillis方法獲取當(dāng)前系統(tǒng)的時(shí)間(毫秒),兩個(gè)時(shí)間之差可以計(jì)算出方法的執(zhí)行時(shí)間闸准,進(jìn)而可以改進(jìn)優(yōu)化益愈。

  4. 獲取系統(tǒng)的內(nèi)存信息

//獲取系統(tǒng)內(nèi)存總數(shù)  
Long total = Runtime.getRuntime().totalMemory();  
//獲取剩余內(nèi)存  
Long free = Runtime.getRuntime().freeMemory();  
//獲取已經(jīng)使用內(nèi)存  
Long used = total – free;

(二)Android省電開發(fā)之CPU降頻

轉(zhuǎn)載自Matrixxu博客專欄

在Android系統(tǒng)的耗電量排行里,cpu的耗電占了比較大的一部分比例夷家,也就是說蒸其,cpu的使用率和使用頻率將直接或間接的影響電量的分配和使用,但很遺憾库快,android-sdk中沒有為android的開發(fā)者提供類似cpu管理的功能摸袁,但是當(dāng)下很多省電類應(yīng)用或?qū)I(yè)的cpu管理軟件都提供了cpu的降頻甚至是超頻的功能,那么這樣的功能是如何實(shí)現(xiàn)的义屏,本文將詳細(xì)說明在android環(huán)境下調(diào)整cpu頻率的一些方法靠汁,僅供參考。

  • CPU的工作頻率
    單位赫茲或者兆赫茲闽铐。CPU的工作頻率越高蝶怔,耗電量越大,反之亦然兄墅。
  • CPU的調(diào)控模式
    英文詞為:Governor踢星,解釋為調(diào)速器,控制器隙咸。android的framework是基于Linux平臺的沐悦,那么cpu的管理體系這塊也跟linux基本上一樣成洗,其中包括cat命令,和一些文件的讀寫配置都是基本上差不多的藏否。Linux在管理CPU方面泌枪,提供了如下幾種調(diào)控模式,分別為:
調(diào)控模式 效果
performance 將CPU的工作頻率調(diào)整到最大模式秕岛,讓CPU充分工作
powersave 將cpu的工作頻率調(diào)整到節(jié)能模式碌燕,這個(gè)模式下的CPU頻率最低
ondemand 定期檢查負(fù)載。當(dāng)負(fù)荷超越了閾值,設(shè)置的CPU運(yùn)行以最高的頻率继薛。當(dāng)負(fù)載低于相同的閾值,設(shè)置的CPU運(yùn)行在下一個(gè)的最低頻率修壕。導(dǎo)致更少的延遲比。ondemand從字面翻譯是“根據(jù)需求遏考,按照需要”慈鸠,cpu在工作的時(shí)候頻率會在一個(gè)最大值和最小值之間波動(dòng),當(dāng)負(fù)載提高時(shí)灌具,該調(diào)控期會自動(dòng)提高cpu的頻率青团,反之亦然】ч梗“Causes less latency than the conservative governor.”這句話的意思是督笆,該模式跟conservative相比,會導(dǎo)致更少的延遲诱贿。ok娃肿,那讓我們再看看conservative是如何解釋的。
conservative 該模式與ondemand的最大區(qū)別在于:conservative模式不會立刻在負(fù)載增加的情況下將cpu頻率調(diào)整到最大珠十,會調(diào)整到比目前頻率稍微大的頻段去工作料扰。所以在某種極端情況下,該模式的延遲會大于ondemand焙蹭。
usersapce 將cpu的掌控權(quán)交給了用戶態(tài)晒杈,也就是交給了應(yīng)用程序,應(yīng)用程序可以通過配置文件的方式修改cpu的頻率信息孔厉。
public class CPUFreqSetting {  
    /** 
     * cpu cat命令大全 
     * cat [%cpuFreqPath%]/cpuinfo_cur_freq   (當(dāng)前cpu頻率) 
     * cat [%cpuFreqPath%]/cpuinfo_max_freq     (最大cpu頻率) 
     * cat [%cpuFreqPath%]/cpuinfo_min_freq     (最小cpu頻率) 
     * cat [%cpuFreqPath%]/related_cpus     (cpu數(shù)量標(biāo)號,從0開始,如果是雙核,結(jié)果為0,1) 
     * cat [%cpuFreqPath%]/scaling_available_frequencies    (cpu所有可用頻率) 
     * cat [%cpuFreqPath%]/scaling_available_governors  (cpu所有可用調(diào)控模式) 
     * cat [%cpuFreqPath%]/scaling_available_governors  (cpu所有可用調(diào)控模式) 
     * cat [%cpuFreqPath%]/scaling_cur_freq     (?????) 
     * cat [%cpuFreqPath%]/scaling_driver   (?????) 
     * cat [%cpuFreqPath%]/scaling_governor (?????) 
     * cat [%cpuFreqPath%]/scaling_max_freq (?????) 
     * cat [%cpuFreqPath%]/scaling_min_freq (?????) 
     * cat [%cpuFreqPath%]/scaling_setspeed (?????) 
     * cat [%cpuFreqPath%]/cpuinfo_transition_latency   (?????) 
     */  
    private final String TAG = "SetCPU";  
    private final String cpuFreqPath = "/sys/devices/system/cpu/cpu0/cpufreq";  
  
    private final static String PERFORMANCE_GOVERNOR = "performance";  
    private final static String POWER_SAVE_GOVERNOR = "performance";  
    private final static String ONDEMAND_GOVERNOR = "performance";  
    private final static String CONSERVATIVE_GOVERNOR = "performance";  
    private final static String USERSAPCE_GOVERNOR = "performance";  
  
//  public void powerSaveGovernor() {  
//      List<String> governors = readCpuGovernors();  
//      if (governors.contains(object)) {  
//  
//      }  
//  }  
  
    /** 
     * 獲得當(dāng)前CPU調(diào)控模式 
     */  
    public void getCpuCurGovernor() {  
        try {  
            DataInputStream is = null;  
            Process process = Runtime.getRuntime().exec("cat " + cpuFreqPath + "/scaling_governor");  
            is = new DataInputStream(process.getInputStream());  
            String line = is.readLine();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
  
    /** 
     * 重寫CPU調(diào)控模式 
     * @param governor 
     * @return 
     */  
    private boolean writeCpuGovernor(String governor) {  
        DataOutputStream os = null;  
        byte[] buffer = new byte[256];  
        String command = "echo " + governor + " > " + cpuFreqPath + "/scaling_governor";  
        Log.i(TAG, "command: " + command);  
        try {  
            Process process = Runtime.getRuntime().exec("su");  
            os = new DataOutputStream(process.getOutputStream());  
            os.writeBytes(command + "\n");  
            os.writeBytes("exit\n");  
            os.flush();  
            process.waitFor();  
            Log.i(TAG, "exit value = " + process.exitValue());  
        } catch (IOException e) {  
            Log.i(TAG, "writeCpuGovernor: write CPU Governor(" + governor + ") failed!");  
            return false;  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        return true;  
    }  
  
    /** 
     * 獲得CPU所有調(diào)控模式 
     * @return 
     */  
    private List<String> readCpuGovernors() {  
        List<String> governors = new ArrayList<String>();  
        DataInputStream is = null;  
        try {  
            Process process = Runtime.getRuntime().exec("cat " + cpuFreqPath + "/scaling_available_governors");  
            is = new DataInputStream(process.getInputStream());  
            String line = is.readLine();  
  
            String[] strs = line.split(" ");  
            for (int i = 0; i < strs.length; i++)  
                governors.add(strs[i]);  
        } catch (IOException e) {  
            Log.i(TAG, "readCpuGovernors: read CPU Governors failed!");  
        }  
        return governors;  
    }  
}

(三)Android省電開發(fā)之service

Android應(yīng)用開發(fā)中拯钻,難免會遇到service開發(fā)。android中服務(wù)是運(yùn)行在后臺的東西烟馅,級別與activity差不多说庭。既然說service是運(yùn)行在后臺的服務(wù)然磷,那么它就是不可見的郑趁,沒有界面的東西。Service和其他組件一樣姿搜,都是運(yùn)行在主線程中寡润,因此不能用它來做耗時(shí)的請求或者動(dòng)作捆憎。你可以在服務(wù)中開一個(gè)線程,在線程中做耗時(shí)動(dòng)作梭纹。

** 我們從三個(gè)方面來淺析一下service的省電開發(fā)**

  • ** 查看service是否存活以及降低優(yōu)先級:**
    假如一個(gè)service工作完成躲惰,但是來不及關(guān)掉或者kill掉,用戶又看不見变抽,所以這個(gè)service將會一直在后臺運(yùn)行础拨,勢必耗電。所以我們可以降低某些不常用service進(jìn)程的優(yōu)先級绍载,在系統(tǒng)內(nèi)存吃緊的情況下诡宗, 進(jìn)程優(yōu)先級低的service容易被系統(tǒng)kill掉。除此之外击儡,可以利用監(jiān)聽系統(tǒng)廣播來判斷service狀態(tài)是否存活塔沃,死亡即可手動(dòng)kill掉。

  • ** 用IntentService代替Service開發(fā):**
    普通服務(wù)一旦啟動(dòng)之后阳谍,就會一直處于運(yùn)行狀態(tài)蛀柴,必須調(diào)用stopService()或者stopSelf()方法才能讓服務(wù)停止下來。為了簡單的創(chuàng)建一個(gè)異步的矫夯、會自動(dòng)挺值得服務(wù)鸽疾,Android專門提供了一個(gè)IntentService類。IntentService在運(yùn)行完畢后自動(dòng)停止训貌,減少耗電量肮韧。

  • ** 后臺執(zhí)行的定時(shí)任務(wù)Alarm機(jī)制:**
    Service沒必要一直在后臺運(yùn)行,這時(shí)候的定時(shí)任務(wù)顯得很重要旺订。
    Android的定時(shí)任務(wù)有兩種實(shí)現(xiàn)方式弄企,Timer類和Alarm機(jī)制。

  • Timer有一個(gè)明顯的短板区拳,不適合長期后臺運(yùn)行的定時(shí)任務(wù)拘领。為了能讓電池更加耐用,每種手機(jī)都會有自己的休眠策略樱调,Android手機(jī)就會在長時(shí)間不操作的情況下自動(dòng)讓CPU進(jìn)入到睡眠狀態(tài)约素,這就有可能導(dǎo)致Timer中的定時(shí)任務(wù)無法正常運(yùn)行。
  • Alarm機(jī)制則不存在這種情況笆凌,它具有喚醒CPU的功能圣猎,即可以保證每次需要執(zhí)行定時(shí)任務(wù)的時(shí)候CPU能正常工作。

? PS:Alarm機(jī)制

從Android 4.4之后乞而,Alarm任務(wù)的觸發(fā)時(shí)間將會變得不準(zhǔn)確送悔,有可能會延遲一段時(shí)間后任務(wù)才能得到執(zhí)行。這不是bug,而是系統(tǒng)在耗電性方面進(jìn)行的優(yōu)化欠啤。系統(tǒng)會自動(dòng)檢測目前有多少Alarm任務(wù)存在荚藻,然后將觸發(fā)時(shí)間將近的幾個(gè)任務(wù)放在一起執(zhí)行,這就可以大幅度的減少CPU被喚醒的次數(shù)洁段,從而有效延長電池的使用時(shí)間应狱。

但是,Android提供了解決方案祠丝,使用AlarmManager的 setExact() 來代替 set() 方法疾呻,基本可以保證任務(wù)準(zhǔn)時(shí)執(zhí)行。

public class MyService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        new Thread() {
            @Override
            public void run() {
                //耗時(shí)操作
            }
        }.run();
        AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        long triggerAtTime = SystemClock.elapsedRealtime() + 10 * 1000;
        Intent intent = new Intent(this, MyService.class);
        PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
        manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pendingIntent);
        return super.onStartCommand(intent, flags, startId);
    }
}
// 讓定時(shí)任務(wù)的觸發(fā)時(shí)間從系統(tǒng)開機(jī)算起写半,不會喚醒CPU
AlarmManager.ELAPSED_REALTIME;        
//讓定時(shí)任務(wù)的觸發(fā)時(shí)間從系統(tǒng)開機(jī)算起罐韩,會喚醒CPU
AlarmManager.ELAPSED_REALTIME_WAKEUP; 
 // 讓定時(shí)任務(wù)的觸發(fā)時(shí)間從1970年1月1日0點(diǎn)算起,不會喚醒CPU
AlarmManager.RTC;    
 // 讓定時(shí)任務(wù)的觸發(fā)時(shí)間從1970年1月1日0點(diǎn)算起污朽,會喚醒CPU                
AlarmManager.RTC_WAKEUP;             
                
// 獲取系統(tǒng)開機(jī)至今所經(jīng)歷時(shí)間的毫秒數(shù)                
SystemClock.elapsedRealtime();    
// 獲取從1970年1月1日0點(diǎn)至今所經(jīng)歷時(shí)間的毫秒數(shù)    
SystemClock.currentThreadTimeMillis();

(四)Android省電開發(fā)之網(wǎng)絡(luò)

除了常規(guī)的異步網(wǎng)絡(luò)散吵、多線程技術(shù)、本地緩存等等之外蟆肆,Android省電開發(fā)還有一個(gè)重要的方面是: WIFI 比蜂窩數(shù)據(jù)更省電:

  • a)盡量在Wi-Fi下傳輸數(shù)據(jù)矾睦,當(dāng)然這是廢話,不過可以考慮在有Wi-Fi的時(shí)候做預(yù)加載炎功,比如應(yīng)用中心的zip包枚冗、手Q web類應(yīng)用的離線資源等;
  • b)非Wi-Fi下,盡量減少網(wǎng)絡(luò)訪問蛇损,每一次后臺交互都要考慮是否必須赁温。雖然WiFi接入方式已經(jīng)占到移動(dòng)互聯(lián)網(wǎng)用戶的50%,但是是有些手機(jī)設(shè)置為待機(jī)關(guān)閉WiFi連接淤齐,即便有Wi-Fi信號也只能切換到蜂窩數(shù)據(jù);

一篇博文中的數(shù)據(jù)測試
滅屏情況:滅屏傳輸填具,高負(fù)載download的時(shí)候WiFi最省電(70mA)碘裕,3G(270mA)和2G(280mA)相當(dāng)括尸,是WiFi的4倍左右;
亮屏情況:亮屏傳輸镀钓,高負(fù)載download的時(shí)候WiFi最省電(280mA),3G(360mA)和2G(370mA)相當(dāng)祭务,是WiFi的1.3倍左右;
所以在Android應(yīng)用省電開發(fā)中内狗,我們可以在獲取網(wǎng)絡(luò)方式的方面加以考慮。


(五)Android省電開發(fā)之Android L5.0(ART)登場

  • 1. 默認(rèn)的ART運(yùn)行模式
    安卓4.4系統(tǒng)中引入了全新的ART模式嗎义锥,相比之前流行已久的Dalvik模式有了很大的改變柳沙。

在Dalvik中,應(yīng)用每次運(yùn)行拌倍,字節(jié)碼都需要通過即時(shí)編譯器轉(zhuǎn)換為機(jī)器碼赂鲤,這回拖慢應(yīng)用的運(yùn)行效率噪径,而在ART環(huán)境中,應(yīng)用在第一次安裝時(shí)蛤袒,字節(jié)碼就會預(yù)先編譯成機(jī)器碼熄云,使其成為了真正的本地應(yīng)用膨更。這個(gè)過程叫做預(yù)編譯妙真。這樣的話,應(yīng)用的啟動(dòng)和執(zhí)行都會變得更加快速荚守。但是ART的缺點(diǎn)是預(yù)編譯完的機(jī)器人占用了更大的存儲空間珍德,應(yīng)用的安裝需要更長的時(shí)間。但是犧牲空間時(shí)間換取省電速度矗漾,在Android應(yīng)用中還是可以接受的锈候,畢竟性能的提升,運(yùn)行速度的變快敞贡,體驗(yàn)更流暢泵琳,電池續(xù)航更久顯得更重要。

  • 2.利用JobScheduler API

過去誊役,如果開發(fā)人員想通過后臺調(diào)取服務(wù)器數(shù)據(jù)获列,或完成某些處理工作,應(yīng)用程序必須先監(jiān)聽是否有事件正在發(fā)生蛔垢,并為自己設(shè)定一個(gè)喚醒時(shí)間击孩,一旦應(yīng)用程序開始運(yùn)行,他需要檢查各種環(huán)境條件鹏漆,以確定是否具備條件讓它完成工作巩梢,還是需要稍后再試,這種方式不僅復(fù)雜艺玲,而且容易出錯(cuò)括蝠,它會不斷的浪費(fèi)資源,比如當(dāng) 一個(gè)應(yīng)用程序被喚醒后饭聚,發(fā)現(xiàn)條件不符合就只能去睡覺并為下次喚醒再次設(shè)定時(shí)間又跛,這是一個(gè)反復(fù)的過程。

這個(gè)問題若治,將引用 JobScheduler 來修復(fù)慨蓝,它作為一個(gè)調(diào)度應(yīng)用程序,負(fù)責(zé)當(dāng)應(yīng)用程序被喚醒時(shí)端幼,提供適當(dāng)?shù)倪\(yùn)行環(huán)境礼烈,所以開發(fā)者不用再讓程序檢測環(huán)境是否符合需求,開發(fā)人員只需要按照標(biāo)準(zhǔn)的流程來婆跑,調(diào)度程序會自動(dòng)為喚醒的程序此熬,準(zhǔn)備好運(yùn)行環(huán)境。應(yīng)用程序可以使用這個(gè)調(diào)度程序,來喚醒他們犀忱,比如當(dāng)設(shè)備連接到充電器后募谎,調(diào)度程序?qū)拘涯切┬枰幚砥鞴ぷ鞯某绦颍屗麄冞M(jìn)行工作阴汇,或者在設(shè)備連接至WiFi網(wǎng)絡(luò)的時(shí)候上傳下載照片数冬,更新內(nèi)容等。該調(diào)度程序還支持一個(gè)時(shí)間窗口搀庶,以便它可以喚醒一組應(yīng)用程序拐纱,這將使那些不需要精確喚醒時(shí)間,但每隔一兩小時(shí)需要運(yùn)行一次的程序能在同一時(shí)間點(diǎn)運(yùn)行哥倔,這樣就能讓處理器保持更長時(shí)間的休眠秸架。

JobScheduler 的優(yōu)勢相當(dāng)巨大,它不僅可以幫助手機(jī)節(jié)省電量咆蒿, 實(shí)際由于不在需要監(jiān)聽东抹,更改和設(shè)置報(bào)警,還可以幫助開發(fā)人員減少代碼書寫量沃测。目前該JobScheduler類缭黔,已經(jīng)加入Android L開發(fā)者預(yù)覽版。

  • 3.各種省電新模式和新技術(shù)
    (1) 全新的Material Design風(fēng)格用戶界面
    新的用戶界面更加簡潔芽突、色彩更加豐富试浙。動(dòng)畫效果更加合理生動(dòng),同時(shí)加入實(shí)時(shí)陰影的3D視圖寞蚌,更多的使用卡片風(fēng)格的顯示效果田巴。全平臺風(fēng)格也變得更為統(tǒng)一。

    (2) 新的通知消息系統(tǒng)
    允許用戶管理通知中心中的通知消息挟秤。原先的Android通知欄幾乎是處于無法控制的狀態(tài)壹哺,所有的應(yīng)用通知都會彈出,要想關(guān)閉只能進(jìn)到每一個(gè)應(yīng)用中去單獨(dú)設(shè)置艘刚,或是使用第三方軟件來實(shí)現(xiàn)統(tǒng)一管理管宵。但是現(xiàn)在不用了,Android 5.0已經(jīng)自帶了通知管理界面攀甚。

    (3) 多任務(wù)界面有著全新的Google Now卡片風(fēng)格
    通知中心融入更多的卡片式風(fēng)格箩朴,即使是在鎖屏狀態(tài)下也可以進(jìn)行多種功能操作。同時(shí)用戶可以自定義通知的優(yōu)先級別秋度,使得用戶不會錯(cuò)過任何重要的通知炸庞。還可以設(shè)置特定的通知權(quán)限,只有被允許的通知消息才會推送荚斯。同時(shí)還具有操作性埠居,比如用戶在游戲時(shí)有電話打入查牌,不會以全屏顯示,而是彈出可操作的通知卡片滥壕,用戶可選擇接聽或拒接纸颜,不影響游戲繼續(xù)進(jìn)行。

    (4) Project Volta省電模式绎橘、BatterySaver省電模式
    Android 5.0的省電模式是通過 JobSchedulerAPI 以及自動(dòng)調(diào)節(jié)屏幕亮度胁孙、刷新率來達(dá)到省電的效果,而且還使用了Project Volta量化每個(gè)應(yīng)用的耗電量金踪,在手機(jī)快沒電的情況下主動(dòng)降低CPU的主頻或者關(guān)閉通訊模塊浊洞,以獲得更長的待機(jī)時(shí)間牵敷。還配備了一個(gè) Battery Bistorian 電池歷史記錄功能胡岔,可讓詳細(xì)顯示設(shè)備的耗電情況。

梳理一下~

以上整理自網(wǎng)絡(luò)~
如有錯(cuò)誤還請大家多多指教啊哈哈

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末枷餐,一起剝皮案震驚了整個(gè)濱河市靶瘸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毛肋,老刑警劉巖怨咪,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異润匙,居然都是意外死亡诗眨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進(jìn)店門孕讳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來匠楚,“玉大人,你說我怎么就攤上這事厂财∮蟛荆” “怎么了?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵璃饱,是天一觀的道長与斤。 經(jīng)常有香客問我,道長荚恶,這世上最難降的妖魔是什么撩穿? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮谒撼,結(jié)果婚禮上食寡,老公的妹妹穿的比我還像新娘。我一直安慰自己嗤栓,他們只是感情好冻河,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布箍邮。 她就那樣靜靜地躺著,像睡著了一般叨叙。 火紅的嫁衣襯著肌膚如雪锭弊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天擂错,我揣著相機(jī)與錄音味滞,去河邊找鬼。 笑死钮呀,一個(gè)胖子當(dāng)著我的面吹牛剑鞍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播爽醋,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼蚁署,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蚂四?” 一聲冷哼從身側(cè)響起光戈,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎遂赠,沒想到半個(gè)月后久妆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡跷睦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年筷弦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抑诸。...
    茶點(diǎn)故事閱讀 40,912評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烂琴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哼鬓,到底是詐尸還是另有隱情监右,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布异希,位于F島的核電站健盒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏称簿。R本人自食惡果不足惜扣癣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望憨降。 院中可真熱鬧父虑,春花似錦、人聲如沸授药。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至莱衩,卻和暖如春爵嗅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背笨蚁。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工睹晒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人括细。 一個(gè)月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓伪很,卻偏偏與公主長得像,于是被迫代替她去往敵國和親奋单。 傳聞我的和親對象是個(gè)殘疾皇子锉试,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,336評論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)辱匿,斷路器键痛,智...
    卡卡羅2017閱讀 134,717評論 18 139
  • 導(dǎo)讀:Android面試中高頻率出現(xiàn)的題都在這了昨忆。試題大部分從互聯(lián)網(wǎng)收集,博主下了一番功夫進(jìn)行梳理總結(jié)杉允,難免有不足...
    Maat紅飛閱讀 55,770評論 61 844
  • 6月18日邑贴,口袋記賬與OPPO可可商店合作發(fā)布獨(dú)家首發(fā)1.5.0版本,界面UI更精致叔磷,操作使用更流暢拢驾,細(xì)節(jié)設(shè)計(jì)更貼...
    小浮生閱讀 610評論 0 1
  • 1.《塵緣》 花季般的流年 墜落萬丈紅塵 青春碎了 塵緣未了 2.《城堡》 漫天的霞光 化作一道道秩序的神鏈 沖入...
    雨韓閱讀 260評論 12 7