Android內存和性能優化 - 教程

1.提供高響應和快速Android應用程序的編程技巧

1.1。為什麼要小心使用Android資源

Android設備的功耗低於標準台式機或筆記本電腦。因此,您必須小心內存消耗。

特別是在Android 5.0之前的Android設備上,您希望避免觸發Java虛擬機的垃圾收集器。這會導致Android運行時凍結約200毫秒。如果用戶例如向下滾動列表,則這可能是顯著的延遲。

1.2。避免不必要的對象分配

避免創建不必要的物體,尤其是在昂貴的地方 儘可能重用對象。創建不必要的對象會更頻繁地觸發垃圾回收,這應該避免。

例如,避免在循環或onDraw()自定義視圖的方法中創建對象。

1.3。使用高效的數據結構

Android提供了幾種Sparse*Array 類的實現。請考慮以下代碼。

Map<Integer, String> map = new HashMap<Integer, String>();

使用此代碼會導致Integer創建不必要的對象。

Android提供的數據結構更有效地將值映射到其他對象。如果可能的話,使用這些對象,就像使用HashMap一樣,它們避免了對象的創建。對象創建可能很昂貴,應該避免以減少垃圾收集器運行所需的次數。

要改進上面的示例,請使用以下數據結構。

SparseArray<String> map = new SparseArray<String>();
map.put(1, "Hello");

2.處理點陣圖

如果以全尺寸載入,點陣圖可以分配大量內存。建議將所需大小的點陣圖載入到內存中。假設您有一個以100x100 dp顯示圖像的應用程序,您應該以這個大小載入圖像。

一種常見的方法是首先測量點陣圖,而不是通過傳遞給它的標誌載入它BitmapFactory

// instruct BitmapFactory to only the bounds and type of the image
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);

// get width and height
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
// type of the image
String imageType = options.outMimeType;

之後,您可以載入圖像的縮放版本。Android非常適合以2的冪來縮放圖像。您可以使用以下方法(來自官方Android文檔)以2為基礎計算比例因子。

public static Bitmap decodeBitmapWithGiveSizeFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {

// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);

// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}

public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {

final int halfHeight = height / 2;
final int halfWidth = width / 2;

// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}

return inSampleSize;
}

此方法可用於將圖像分配給視圖,如以下示例所示。

viewWidth = imageView.getWidth();
viewHeight = imageView.getHeight();

imageView.
imageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, viewWidth, viewHeight));

3.1。使用緩存

緩存允許重用創建昂貴的對象。如果將對象載入到內存中,則可以將其視為對象的緩存。例如,如果從Internet下載圖像以在列表中顯示它們,則應將它們保存在內存中以避免多次下載它們。

在某些時候,您需要回收一些對象,否則會耗盡內存。這樣做的一個好方法是回收在應用程序中使用時間最長的對象。

Android平台提供了 LruCache 類,從API 12開始(或在support-v4庫中)。本LruCache 類提供了一個least最近使用的緩存(LRU高速緩存)的緩存實現。LRU緩存會跟蹤其成員的使用情況。它具有給定的大小,如果超過此大小,則會刪除最長時間未訪問的項目。此行為如下圖所示。

以下示例代碼演示了LruCache用於緩存圖像的類的可能實現。

public class ImageCache extends LruCache<String, Bitmap> {

public ImageCache( int maxSize ) {
super( maxSize );
}

@Override
protected int sizeOf( String key, Bitmap value ) {
return value.getByteCount();
}

@Override
protected void entryRemoved( boolean evicted, String key, Bitmap oldValue, Bitmap newValue ) {
oldValue.recycle();
}

}

它的用法很簡單,並通過以下示例代碼進行說明。

LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>();

為了確定高速緩存的初始大小,最好根據設備上可用的總內存來確定大小。為了確定可用的內存你可以MemoryClass。以下代碼對此進行了演示。

int memClass = ( ( ActivityManager) activity.getSystemService( Context.ACTIVITY_SERVICE ) ).getMemoryClass();
int cacheSize = 1024 * 1024 * memClass / 8;
LruCache cache = new LruCache<String, Bitmap>( cacheSize );

3.2。清理緩存

從API 14開始,您可以覆蓋onTrimMemory()Android組件中的方法。Android系統調用此方法,要求您在Android系統需要前台進程資源的情況下清理內存。

4.鏈接和文獻

需要相關文檔鏈接可以私信我 資料 希望大家多多關注和點贊~

歡迎大家加入Android開發圈~


推薦閱讀:

TAG:Android | Android開發 | 性能優化 |