1. 程式人生 > >阿里Android開發規範:Bitmap、Drawable 與動畫

阿里Android開發規範:Bitmap、Drawable 與動畫

以下內容摘自 阿里巴巴Android開發手冊

我們的目標是:

  • 防患未然,提升質量意識,降低故障率和維護成本;
  • 標準統一,提升協作效率;
  • 追求卓越的工匠精神,打磨精品程式碼。
  • 【強制】必須遵守,違反本約定或將會引起嚴重的後果;
  • 【推薦】儘量遵守,長期遵守有助於系統穩定性和合作效率的提升;
  • 【參考】充分理解,技術意識的引導,是個人學習、團隊溝通、專案合作的方向。

1、【強制】載入大圖片或者一次性載入多張圖片,應該在非同步執行緒中進行。圖片的載入,涉及到 IO 操作,以及 CPU 密集操作,很可能引起卡頓。
正例:

class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
    ...
// 在後臺進行圖片解碼 @Override protected Bitmap doInBackground(Integer... params) { final Bitmap bitmap = BitmapFactory.decodeFile("some path"); return bitmap; } ... }

反例:

Button btnLoadImage = (Button) findViewById(R.id.btn);
btnLoadImage.setOnClickListener(new OnClickListener(){
    public
void onClick(View v) { Bitmap bitmap = BitmapFactory.decodeFile("some path"); } });
private LruCache<String, Bitmap> mMemoryCache;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        // 獲取可用記憶體的最大值,使用記憶體超出這個值將丟擲 OutOfMemory 異常。LruCache 通過建構函式傳入快取值,以 KB 為單位。
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // 把最大可用記憶體的 1/8 作為快取空間 final int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getByteCount() / 1024; } }; ... } public void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } public Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); } public void loadBitmap(int resId, ImageView imageView) { final String imageKey = String.valueOf(resId); final Bitmap bitmap = getBitmapFromMemCache(imageKey); if (bitmap != null) { mImageView.setImageBitmap(bitmap); } else { mImageView.setImageResource(R.drawable.image_placeholder); BitmapWorkerTask task = new BitmapWorkerTask(mImageView); task.execute(resId); } } class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> { ... // 在後臺進行圖片解碼 @Override protected Bitmap doInBackground(Integer... params) { final Bitmap bitmap = decodeSampledBitmapFromResource(getResources(), params[0], 100, 100)); addBitmapToMemoryCache(String.valueOf(params[0]), bitmap); return bitmap; } ... }

反例:
沒有儲存,每次都需要解碼,或者有快取但是沒有合適的淘汰機制,導致快取效果很差,依然經常需要重新解碼。
3、【強制】png 圖片使用 tinypng 或者類似工具壓縮處理,減少包體積。
4、【推薦】應根據實際展示需要,壓縮圖片,而不是直接顯示原圖。手機螢幕比較小,直接顯示原圖,並不會增加視覺上的收益,但是卻會耗費大量寶貴的記憶體。
正例:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,int reqWidth, int reqHeight) {
    // 首先通過 inJustDecodeBounds=true 獲得圖片的尺寸
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);
    // 然後根據圖片解析度以及我們實際需要展示的大小,計算壓縮率
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    // 設定壓縮率,並解碼
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

反例:
不經壓縮顯示原圖。
5、【強制】使用完畢的圖片,應該及時回收,釋放寶貴的記憶體。
正例:

Bitmap bitmap = null;
loadBitmapAsync(new OnResult(result){
    bitmap = result;
});
...使用該 bitmap...
// 使用結束,在 2.3.3 及以下需要呼叫 recycle()函式,在 2.3.3 以上 GC 會自動管理,除非你明確不需要再用。
if (Build.VERSION.SDK_INT <= 10) {
    bitmap.recycle();
}
bitmap = null;

反例:
使用完成圖片,始終不釋放資源。
6、【推薦】針對不同的螢幕密度,提供對應的圖片資源,使記憶體佔用和顯示效果達到合理的平衡。如果為了節省包體積,可以在不影響 UI 效果的前提下,省略低密度圖片。
7、【強制】在 Activity.onPause()或 Activity.onStop()回撥中,關閉當前 activity 正在執行的的動畫。
正例

public class MyActivity extends Activity {
    ImageView mImageView;
    Animation mAnimation;
    Button mBtn;
    /** 首次建立 activity 時呼叫 */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mImageView = (ImageView)findViewById(R.id.ImageView01);
        mAnimation = AnimationUtils.loadAnimation(this, R.anim.anim);
        mBtn= (Button)findViewById(R.id.Button01);
        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            mImageView.startAnimation(mAnimation);
            }
        });
    }

    public void onPause() {
        //頁面退出,及時清理動畫資源
        mImageView.clearAnimation()
    }
}

反例:
頁面退出時,不關閉該頁面相關的動畫。
8、【推薦】在動畫或者其他非同步任務結束時,應該考慮回撥時刻的環境是否還支援業務處理。例如 Activity 的 onStop()函式已經執行,且在該函式中主動釋放了資源,此時回撥中如果不做判斷就會空指標崩潰。
正例:

public class MyActivity extends Activity {
    private ImageView mImageView;
    private Animation mAnimation;
    /** 首次建立 activity 時呼叫 */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mImageView = (ImageView)findViewById(R.id.ImageView01);
        mAnimation = AnimationUtils.loadAnimation(this, R.anim.anim);
        mAnimation.setAnimationListener(new AnimationListener() {
            @Override
            public void onAnimationEnd(Animation arg0) {
                //判斷一下資源是否被釋放了
                if (mImageView != null) {
                    mImageView.clearAnimation();
                }
            }
        });
        mImageView.startAnimation(mAnimation);
    }
}

反例:
動畫結束回撥中,直接使用資源不加判斷,導致異常。
9、【推薦】使用 inBitmap 重複利用記憶體空間,避免重複開闢新記憶體。
正例:

public static Bitmap decodeSampledBitmapFromFile(String filename, int reqWidth, intreqHeight, ImageCache cache) {
    final BitmapFactory.Options options = new BitmapFactory.Options();
    ...
    BitmapFactory.decodeFile(filename, options);
    ...
    // 如果在 Honeycomb 或更新版本系統中執行,嘗試使用 inBitmap
    if (Utils.hasHoneycomb()) {
        addInBitmapOptions(options, cache);
    }
    ...
    return BitmapFactory.decodeFile(filename, options);
}

private static void addInBitmapOptions(BitmapFactory.Options options,ImageCache cache) {
    // inBitmap 只處理可變的點陣圖,所以強制返回可變的點陣圖
    options.inMutable = true;
    if (cache != null) {
        Bitmap inBitmap = cache.getBitmapFromReusableSet(options);
        if (inBitmap != null) {
            options.inBitmap = inBitmap;
        }
    }
}

10、【推薦】使用 ARGB_565 代替 ARGB_888,在不怎麼降低視覺效果的前提下,減少記憶體佔用。
說明:
android.graphics.Bitmap.Config 類中關於圖片顏色的儲存方式定義:

  1. ALPHA_8 代表 8 位 Alpha 點陣圖;
  2. ARGB_4444 代表 16 位 ARGB 點陣圖;
  3. ARGB_8888 代表 32 位 ARGB 點陣圖;
  4. RGB_565 代表 8 位 RGB 點陣圖。

點陣圖位數越高,儲存的顏色資訊越多,影象也就越逼真。大多數場景使用的是ARGB_8888 和 RGB_565,RGB_565 能夠在保證圖片質量的情況下大大減少記憶體的開銷,是解決 oom 的一種方法。但是一定要注意 RGB_565 是沒有透明度的,如果圖片本身需要保留透明度,那麼就不能使用 RGB_565。
正例:

Config config = drawableSave.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888 :
Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(w, h, config);

反例:

Bitmap newb = Bitmap.createBitmap(width, height, Config.ARGB_8888);

擴充套件參考:

11、【推薦】儘量減少 Bitmap (BitmapDrawable)的使用,儘量使用純色(ColorDrawable)、漸變色(GradientDrawable)、StateSelector(StateListDrawable)等與 Shape 結合的形式構建繪圖。
12、【推薦】謹慎使用 gif 圖片,注意限制每個頁面允許同時播放的 gif 圖片,以及單個gif 圖片的大小。
13、【參考】大圖片資源不要直接打包到 apk,可以考慮通過檔案倉庫遠端下載,減小包
體積。
14、【推薦】根據裝置效能,選擇性開啟複雜動畫,以實現一個整體較優的效能和體驗;
15、【推薦】在有強依賴 onAnimationEnd 回撥的互動時,如動畫播放完畢才能操作頁面 , onAnimationEnd 可 能 會 因 各 種 異 常 沒 被 回 調 ( 參 考 :https://stackoverflow.com/questions/5474923/onanimationend-is-not-getting-called-onanimationstart-works-fine),建議加上超時保護或通過 postDelay 替代onAnimationEnd。
正例:

View v = findViewById(R.id.xxxViewID);
final FadeUpAnimation anim = new FadeUpAnimation(v);
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(1000);
anim.setFillAfter(true);
new Handler().postDelayed(new Runnable() {
    public void run() {
        if (v != null) {
            v.clearAnimation();
        }
    }
}, anim.getDuration());
v.startAnimation(anim);

16、【推薦】當 View Animation 執行結束時,呼叫 View.clearAnimation()釋放相關資源。
正例:

View v = findViewById(R.id.xxxViewID);
final FadeUpAnimation anim = new FadeUpAnimation(v);
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(1000);
anim.setFillAfter(true);
anim.setAnimationListener(new AnimationListener() {
    @Override
    public void onAnimationEnd(Animation arg0) {
        //判斷一下資源是否被釋放了
        if (v != null) {
            v.clearAnimation();
        }
    }
});
v.startAnimation(anim);

相關推薦

阿里Android開發規範BitmapDrawable 動畫

以下內容摘自 阿里巴巴Android開發手冊 我們的目標是: 防患未然,提升質量意識,降低故障率和維護成本; 標準統一,提升協作效率; 追求卓越的工匠精神,打磨精品程式碼。 【強制】必須遵守,違反本約定或將會引起嚴重的後果; 【推薦】儘量遵守,長期遵守有助

阿里Android開發規範四大基本元件

以下內容摘自 阿里巴巴Android開發手冊 我們的目標是: 防患未然,提升質量意識,降低故障率和維護成本; 標準統一,提升協作效率; 追求卓越的工匠精神,打磨精品程式碼。 【強制】必須遵守,違反本約定或將會引起嚴重的後果; 【推薦】儘量遵守,長期遵守有助

阿里Android開發規範安全其他

以下內容摘自 阿里巴巴Android開發手冊 我們的目標是: 防患未然,提升質量意識,降低故障率和維護成本; 標準統一,提升協作效率; 追求卓越的工匠精神,打磨精品程式碼。 【強制】必須遵守,違反本約定或將會引起嚴重的後果; 【推薦】儘量遵守,長期遵守有助

Android開發規範包命名規範

簡介 android包目錄的命名的好壞,會直接影響到整個app工程後期的開發效率和擴充套件性。 所以在建立專案的初期,建立一個好的包目錄的命名非常重要。 一般來說android包命名的方式有兩種:PBL和PBF。 我們現在分別來介紹下這兩種命名規則以及各自的優缺點。

Android開發規範程式碼規範(CheckStyle)

文章目錄 checkstyle: plugin checkstyle: gradle checkstyle: 155條規範 開發APP的過程中,每個團隊都會約定自己的程式碼規範。但是往往在實踐過程中,要麼由於開發週

Android開發規範資原始檔命名規範

文章目錄 layout layout中的id anim drawable values中的id layout 全部小寫,採用下劃線命名法,使用名詞或名詞片語。 所有Activity或Fragme

Android開發規範Java命名規範

文章目錄 類名 方法名 變數名 類名 採用大駝峰命名法。 命名規則:功能+型別(Activity、Adapter、Service等)。 舉例: activity類,命名以Activity為字尾

Android開發規範Android Studio規範

儘量使用最新版的IDE進行開發; 編碼格式統一為UTF-8; 編輯完.java、 .xml等檔案後一定要格式化(基本格式方面使用 AS 預設模板即可); 刪除多餘的import,減少警告出現,可利用AS的Optimize Imports(Setti

阿里Android開發手冊筆記---程序執行緒訊息

1、不要通過 Intent 在 Android 基礎元件之間傳遞大資料(binder transaction 快取為 1MB),可能導致 OOM。 2、在 Application 的業務初始化程式碼加入程序判斷,確保只在自己需要的程序 初始化。特別是後臺程序減少不必要的

Android開發規範日誌Log

文章目錄 1. 現有的系統Log 2. 改進的Log工具 3. 從日誌模組談擴充套件性 Log對於開發者定位問題來說是一個必不可少的工具。開發人員需要通過Log提供的資訊,比如Crash異常,能夠定位異常型別以及異常的

Android開發規範JavaDoc

文章目錄 1. JavaDoc的配置 2. JavaDoc的輸出 3. 常見問題 4. 使用gradle指令碼 1. JavaDoc的配置 2. JavaDoc的輸出 Tools → Gene

開發規範阿里巴巴Android開發手冊》之初理解

今天一早就看見了《阿里巴巴Android開發手冊》開放下載的推送。該開發規範在阿里內部經過了長期的修繕,現已總結成冊,向所有移動開發者、技術愛好者開放,希望幫助開發者碼出高效、碼出質量,提升系統的質量、協作的高效性。粗略翻閱一遍後,總結出部分規範。日後再當

IDEAL葵花寶典java程式碼開發規範外掛 checkstylevisualVMPMD 外掛

前言: visualVM: 執行java程式的時候啟動visualvm,方便檢視jvm的情況 比如堆記憶體大小的分配;某個物件佔用了多大的記憶體,jvm調優必備工具。 checkstyle: CheckStyle是SourceForge下的一個專案,提供了一個幫助JAVA開發人員遵守某些編碼規範的工具。   

前端開發規範命名規範html規範css規範js規範

本文首發於我的個人網站:http://cherryblog.site/ (背景更換了不知道大家有沒有發現呢,嘻嘻) 一個好的程式設計師肯定是要能書寫可維護的程式碼,而不是一次性的程式碼,怎麼能讓團隊當中其他人甚至一段時間時候你再看你某個時候寫

Android 繪圖基礎Bitmap(點陣圖)Matrix(矩陣)實現圖片5種操作(平移旋轉錯切縮放對稱)

Android的Matrix利用數學原理實現圖片平移、旋轉等操作詳解   很慶幸自己的線性代數學的還可以,理解Matrix的矩陣變換完全沒有問題。Matrix矩陣實現圖片的平移旋轉等操作涉及到線性代數問題,感興趣它的具體實現的話可以參考一下上面的部落格,非常詳

Android引路蜂地圖開發示例放大縮小

RasterMap的 zoomIn,zoomOut 用來放大縮小地圖。在專案GISEngineTutorial中建立MapZoom Activity。 package com.pstreets.gisengine.demo; import com.mapdigit.gi

Android開發實踐JNI層線程回調Java函數示例

lan 並且 進行 img 工程 stat 責任 3.5 jpg 原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://ticktick.blog.51cto.com/823160/1358558 JNI是Ja

aNDROID開發82787450

list com and 5% sdk ongl .com hao123 andro %E8%AF%B7%E9%97%AE%E9%82%A3%E5%AE%B6%E7%9A%84%E5%B9%BF%E5%91%8AsDk%E5%A5%BD%E5%95%8A http://m

值得你學習的 Android 開發規範(上)

web 數字 文件規範 () base lan 都是 3.5 tsp 前言 AS規範 命名規範 資源文件規範 版本統一規範 第三方庫規範 註釋規範 其他的一些規範 1 前言 為了利於項目維護以及規範開發,促進成員之間Code Revi

Android 程序架構 MVCMVPMVVMUnidirectionalClean...

不同 概念 可能 十年 tin gettext 聲明 數據 content 摘選自:GUI 應用程序架構的十年變遷:MVC、MVP、MVVM、Unidirectional、Cleanhttps://zhuanlan.zhihu.com/p/26799645 MV