Android設備的功耗低於標準台式機或筆記本電腦。因此,您必須小心內存消耗。
特別是在Android 5.0之前的Android設備上,您希望避免觸發Java虛擬機的垃圾收集器。這會導致Android運行時凍結約200毫秒。如果用戶例如向下滾動列表,則這可能是顯著的延遲。
避免創建不必要的物體,尤其是在昂貴的地方 儘可能重用對象。創建不必要的對象會更頻繁地觸發垃圾回收,這應該避免。
例如,避免在循環或onDraw()自定義視圖的方法中創建對象。
onDraw()
Android提供了幾種Sparse*Array 類的實現。請考慮以下代碼。
Sparse*Array
Map<Integer, String> map = new HashMap<Integer, String>();
使用此代碼會導致Integer創建不必要的對象。
Android提供的數據結構更有效地將值映射到其他對象。如果可能的話,使用這些對象,就像使用HashMap一樣,它們避免了對象的創建。對象創建可能很昂貴,應該避免以減少垃圾收集器運行所需的次數。
要改進上面的示例,請使用以下數據結構。
SparseArray<String> map = new SparseArray<String>(); map.put(1, "Hello");
如果以全尺寸載入,點陣圖可以分配大量內存。建議將所需大小的點陣圖載入到內存中。假設您有一個以100x100 dp顯示圖像的應用程序,您應該以這個大小載入圖像。
一種常見的方法是首先測量點陣圖,而不是通過傳遞給它的標誌載入它BitmapFactory。
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));
緩存允許重用創建昂貴的對象。如果將對象載入到內存中,則可以將其視為對象的緩存。例如,如果從Internet下載圖像以在列表中顯示它們,則應將它們保存在內存中以避免多次下載它們。
在某些時候,您需要回收一些對象,否則會耗盡內存。這樣做的一個好方法是回收在應用程序中使用時間最長的對象。
Android平台提供了 LruCache 類,從API 12開始(或在support-v4庫中)。本LruCache 類提供了一個least最近使用的緩存(LRU高速緩存)的緩存實現。LRU緩存會跟蹤其成員的使用情況。它具有給定的大小,如果超過此大小,則會刪除最長時間未訪問的項目。此行為如下圖所示。
LruCache
以下示例代碼演示了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 );
從API 14開始,您可以覆蓋onTrimMemory()Android組件中的方法。Android系統調用此方法,要求您在Android系統需要前台進程資源的情況下清理內存。
onTrimMemory()
需要相關文檔鏈接可以私信我 資料 希望大家多多關注和點贊~
歡迎大家加入Android開發圈~
TAG:Android | Android開發 | 性能優化 |