編輯:安卓省電與加速
傳統軟件的UI繪制是依靠CPU來完成的,硬件加速就是將繪制任務交由GPU來執行。GPU相比CPU更加適合完成光柵化、動畫變換等耗時任務,在移動設備上比起使用CPU來完成這些任務,GPU會更加省電些,帶來的用戶體驗也會更佳。
Android的硬件加速的底層實現是基於OpenGL ES接口向GPU提交指令來完成繪制的。相對於CPU實現的軟繪制,硬件加速的幀率會高於CPU,效能更高。屏幕分辨率越大(尤其對於高清電視而言),硬件加速的優勢更加明顯。
下圖是Android 5.0的HWUI繪制執行流程:
源碼位於目錄android/platform/framework/base/libs/hwui<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
......
public void buildLayer() {
......
final AttachInfo attachInfo = mAttachInfo;
......
switch (mLayerType) {
case LAYER_TYPE_HARDWARE:
updateDisplayListIfDirty();
if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
}
break;
case LAYER_TYPE_SOFTWARE:
buildDrawingCache(true);
break;
}
}
......
}
當View的LayerType設置為HARDWARE時,View就會綁定到一個OpenGL ES的FrameBufferObject上去,如果要對這個View進行Animation(Alpha,Rotation,etc.),會將這個FrameBufferObject渲染至Texture(2D),然後再進行動畫的渲染,這樣有一個壞處,消耗的內存增加了。
在Android 5上,ThreadedRenderer的出現減輕了主線程的負擔,可以更快的響應用戶的操作。
DisplayList記錄了繪制操作和狀態,主線程將它們提交至OpenGL渲染器,由渲染器執行最終的DrawCall。
Android 4.4之後,HWUI模塊引入了Deferred Display List,它在Display List的基礎上做了一些優化,比如剔除過繪制的區域、對DrawCall進行分批或合並,在一定程度上提升了繪制的性能。
seo8L3N0cm9uZz6jrMq5VUnSwMi7xNy5u9X9yLe75tbGoaM8L3A+DQo8L2Jsb2NrcXVvdGU+DQo8cD7I57n7yeixuNans9ZPcGVuR0wgRVMgMy4wo6xBbmRyb2lku+HKudPDPHN0cm9uZz5QaXhlbEJ1ZmZlck9iamVjdLDztqg8L3N0cm9uZz7Ktc/WzsbA7bXE0uyyvcnPtKujrNXi0fnX9rXEusO0ptTa09rNqLn907PJ5Le9yr2jqGdsTWFwQnVmZmVyo6m4/LzTuN/Qp7XEyc+0q87GwO3K/b7d1sFHUFWho8/Cw+bV4rbOtPrC68C019TT2tfAw+a2y7XEyrXP1qOs0sa2r7bLtcTKtc/Wsu7S7LK7tPOhozwvcD4NCjxwcmUgY2xhc3M9"brush:java;">
// 綁定紋理單元和PBO
glBindTexture(GL_TEXTURE_2D, textureId);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[index]);
// 將PBO的像素復制到紋理中去
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, 0);
//准備上傳下一份紋理
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[nextIndex]);
//這裡如果直接調用glMapBuffer會引起OpenGL狀態機的一個同步檢查(開銷較大),但是使用BufferData的話就不會,他可以直接分配完數據返回
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, DATA_SIZE, 0, GL_STREAM_DRAW_ARB);
//將GPU數據映射至內存
GLubyte* ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
if(ptr) {
updatePixels(ptr, DATA_SIZE); //直接更新紋理數據
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // 釋放映射的緩沖區
}
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
ATLAS的使用減少了GPU顯存的消耗,以及紋理單元(Texture Unit)綁定調用(Resource Binding)的開銷。
Android硬件加速的過程中並沒有啟用深度測試(DepthTest),所有的UI繪制都是按照繪制的次序展示在屏幕上。由於OpenGL ES的驅動實現的復雜性,每個GL的綁定調用以及GL狀態的切換都是昂貴的,所以才引入了Deferred Display List對DrawCall合並以及分批,相關類,如上圖。
文字的渲染也是一個令人頭疼的問題,APP的文字渲染不像游戲中那樣的簡單,通常游戲發布的時候可以預先將固定的文字轉換成單張的紋理,渲染文字時直接映射紋理坐標即可。Android底層對文字字形紋理數據進行了Cache。Android使用了Skia和第三方開源字體庫(FreeType)對字體進行柵格化。
iOS的UI繪制使用了Multiple GL Context,在iOS 8之後又引入了Metal Framework,原生支持多線程UI渲染,Android由於GL驅動以及GPU廠商實現的差異無法很好地搾干GPU的機能,但是在下一代的圖形API(Vulkan,驅動變薄、支持多線程)普及之後,仍然有較大的優化空間,UI流暢性可以進一步提升。
你也許還沒有注意到,Android 5.0 Lollipop版本統正式加入了電池保護模式。這一功能的引進,幫助Android用戶徹底告別了需要尋找第三方
電量不夠用大概是所有安卓手機用戶們的一個心頭病,同時現在這也是很多廠商們努力的方向,因此現在市場上也有不少的大容量電池的手機紛紛湧現。但是如果用戶本身沒有一個很好的用機習
努比亞Z7 Mini手機省電模式如何開啟呢?手續電池的續航問題一直制約著手機的使用,那麼這手機的省電模式就很重要了
筆者個人的省電方式主要有兩種:1.不獲取手機最高權限的“屌絲”省電法。2.獲取ROOT最高權限,給手機做大手術最到極致省電方法。要記得一點,手機廠