當前位置:首頁 » 存儲配置 » hbasebitmap如何存儲

hbasebitmap如何存儲

發布時間: 2023-12-14 06:14:18

1. 如何高效使用和管理Bitmap

一、圖片載入流程

首先,我們談談載入圖片的流程,項目中的該模塊處理流程如下:

1.在UI主線程中,從內存緩存中獲取圖片,找到後返回。找不到進入下一步;

2.在工作線程中,從磁碟緩存中獲取圖片,找到即返回並更新內存緩存。找不到進入下一步;

3.在工作線程中,從網路中獲取圖片,找到即返回並同時更新內存緩存和磁碟緩存。找不到顯示默認以提示。

二、內存緩存類(PanoMemCache)


這里使用Android提供的LruCache類,該類保存一個強引用來限制內容數量,每當Item被訪問的時候,此Item就會移動到隊列的頭部。當cache已滿的時候加入新的item時,在隊列尾部的item會被回收。


[java] view plain print ?

public class PanoMemoryCache {

// LinkedHashMap初始容量

private static final int INITIAL_CAPACITY = 16;

// LinkedHashMap載入因子

private static final int LOAD_FACTOR = 0.75f;

// LinkedHashMap排序模式

private static final boolean ACCESS_ORDER = true;

// 軟引用緩存

private static LinkedHashMap<String, SoftReference<Bitmap>> mSoftCache;

// 硬引用緩存

private static LruCache<String, Bitmap> mLruCache;

public PanoMemoryCache() {

// 獲取單個進程可用內存的最大值

// 方式一:使用ActivityManager服務(計量單位為M)

/*int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();*/

// 方式二:使用Runtime類(計量單位為Byte)

final int memClass = (int) Runtime.getRuntime().maxMemory();

// 設置為可用內存的1/4(按Byte計算)

final int cacheSize = memClass / 4;

mLruCache = new LruCache<String, Bitmap>(cacheSize) {

@Override

protected int sizeOf(String key, Bitmap value) {

if(value != null) {

// 計算存儲bitmap所佔用的位元組數

return value.getRowBytes() * value.getHeight();

} else {

return 0;

}

}

@Override

protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {

if(oldValue != null) {

// 當硬引用緩存容量已滿時,會使用LRU演算法將最近沒有被使用的圖片轉入軟引用緩存

mSoftCache.put(key, new SoftReference<Bitmap>(oldValue));

}

}

};

/*

* 第一個參數:初始容量(默認16)

* 第二個參數:載入因子(默認0.75)

* 第三個參數:排序模式(true:按訪問次數排序;false:按插入順序排序)

*/

mSoftCache = new LinkedHashMap<String, SoftReference<Bitmap>>(INITIAL_CAPACITY, LOAD_FACTOR, ACCESS_ORDER) {

private static final long serialVersionUID = 7237325113220820312L;

@Override

protected boolean removeEldestEntry(Entry<String, SoftReference<Bitmap>> eldest) {

if(size() > SOFT_CACHE_SIZE) {

return true;

}

return false;

}

};

}

/**

* 從緩存中獲取Bitmap

* @param url

* @return bitmap

*/

public Bitmap getBitmapFromMem(String url) {

Bitmap bitmap = null;

// 先從硬引用緩存中獲取

synchronized (mLruCache) {

bitmap = mLruCache.get(url);

if(bitmap != null) {

// 找到該Bitmap之後,將其移到LinkedHashMap的最前面,保證它在LRU演算法中將被最後刪除。

mLruCache.remove(url);

mLruCache.put(url, bitmap);

return bitmap;

}

}

// 再從軟引用緩存中獲取

synchronized (mSoftCache) {

SoftReference<Bitmap> bitmapReference = mSoftCache.get(url);

if(bitmapReference != null) {

bitmap = bitmapReference.get();

if(bitmap != null) {

// 找到該Bitmap之後,將它移到硬引用緩存。並從軟引用緩存中刪除。

mLruCache.put(url, bitmap);

mSoftCache.remove(url);

return bitmap;

} else {

mSoftCache.remove(url);

}

}

}

return null;

}

/**

* 添加Bitmap到內存緩存

* @param url

* @param bitmap

*/

public void addBitmapToCache(String url, Bitmap bitmap) {

if(bitmap != null) {

synchronized (mLruCache) {

mLruCache.put(url, bitmap);

}

}

}

/**

* 清理軟引用緩存

*/

public void clearCache() {

mSoftCache.clear();

mSoftCache = null;

}

}

補充一點,由於4.0平台以後對SoftReference類引用的對象調整了回收策略,所以該類中的軟引用緩存實際上沒什麼效果,可以去掉。2.3以前平台建議保留。

三、磁碟緩存類(PanoDiskCache)

五、使用decodeByteArray()還是decodeStream()?

講到這里,有童鞋可能會問我為什麼使用BitmapFactory.decodeByteArray(data, 0, data.length, opts)來創建Bitmap,而非使用BitmapFactory.decodeStream(is, null, opts)。你這樣做不是要多寫一個靜態方法readInputStream()嗎?

沒錯,decodeStream()確實是該使用情景下的首選方法,但是在有些情形下,它會導致圖片資源不能即時獲取,或者說圖片被它偷偷地緩存起來,交 還給我們的時間有點長。但是延遲性是致命的,我們等不起。所以在這里選用decodeByteArray()獲取,它直接從位元組數組中獲取,貼近於底層 IO、脫離平台限制、使用起來風險更小。

六、引入緩存機制後獲取圖片的方法

[java] view plain print ?

/**

* 載入Bitmap

* @param url

* @return

*/

private Bitmap loadBitmap(String url) {

// 從內存緩存中獲取,推薦在主UI線程中進行

Bitmap bitmap = memCache.getBitmapFromMem(url);

if(bitmap == null) {

// 從文件緩存中獲取,推薦在工作線程中進行

bitmap = diskCache.getBitmapFromDisk(url);

if(bitmap == null) {

// 從網路上獲取,不用推薦了吧,地球人都知道~_~

bitmap = PanoUtils.downloadBitmap(this, url);

if(bitmap != null) {

diskCache.addBitmapToCache(bitmap, url);

memCache.addBitmapToCache(url, bitmap);

}

} else {

memCache.addBitmapToCache(url, bitmap);

}

}

return bitmap;

}

七、工作線程池化

有關多線程的切換問題以及在UI線程中執行loadBitmap()方法無效的問題,請參見另一篇博文: 使用嚴苛模式打破Android4.0以上平台應用中UI主線程的「獨斷專行」。

有關工作線程的處理方式,這里推薦使用定製線程池的方式,核心代碼如下:

[java] view plain print ?

// 線程池初始容量

private static final int POOL_SIZE = 4;

private ExecutorService executorService;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// 獲取當前使用設備的CPU個數

int cpuNums = Runtime.getRuntime().availableProcessors();

// 預開啟線程池數目

executorService = Executors.newFixedThreadPool(cpuNums * POOL_SIZE);

...

executorService.submit(new Runnable() {

// 此處執行一些耗時工作,不要涉及UI工作。如果遇到,直接轉交UI主線程

pano.setImage(loadBitmap(url));

});

...

}

我們知道,線程構造也是比較耗資源的。一定要對其進行有效的管理和維護。千萬不要隨意而行,一張圖片的工作線程不搭理也許沒什麼,當使用場景變為 ListView和GridView時,線程池化工作就顯得尤為重要了。Android不是提供了AsyncTask嗎?為什麼不用它?其實 AsyncTask底層也是靠線程池支持的,它默認分配的線程數是128,是遠大於我們定製的executorService。

2. Android Bitmap理解

參考:
Android Bitmap 詳解:關於 Bitamp 你所要知道的一切

Android Bitmap(點陣圖)詳解

圖片是由大量且有限個數的像素點組成。把一張圖片通過bitmap的方式創建到內存中,實際上就是在內存中創建了一個叫做Bitmap的對象,然後把 圖片所有像素 解碼後的數據存放在Bitmap對象裡面,Bitmap就擁有了圖片的寬高,透明度,顏色值等數據。所以Bitmap的創建是通過BitmapFactory.decodeXxx()。

Config是Bitmap類中的枚舉類。像素由ARGB四個顏色通道組成。Config描述點陣圖中像素的存儲方式。 這里的存儲方式,無非就是對顏色通道和用多大的容器(bit)來存儲的排列組合。所以config會影響圖片透明度,佔用內存大小,保存成文件的大小,圖片質量。
Config的字母表示該配置存儲的像素的顏色通道,數字表示對應通道的數據用多少位來存儲。

ALPHA_8:表示只存儲alpha通道,使用8bit(1位元組)的內存(容器)來存儲一個像素。
RGB_565:表示存儲RGB三個通道,分別使用5bit,6bit,5bit的內存(容器)來存儲一個像素。
ARGB_4444:表示存儲ARGB四個通道,每個通道都是以4bit的內存(容器)來存儲一個像素。
ARGB_8888:表示存儲ARGB四個通道,每個通道都是以8bit的內存(容器)來存儲一個像素。

所以,ARGB_8888配置佔用內存最大,圖片質量最高。
圖片壓縮的一個思路就是降低圖片的配置。

總內存 = 寬的像素數 × 高的像素數 × 每個像素點佔用的大小
註:
1 byte = 8 bit
1 KB = 1024 byte

3. android中怎麼用sqlite存儲一個map

在進行Android開發過程中,我們經常會接觸到Drawable對象(官方開發文檔:A Drawable is a general abstraction for "something that can be drawn."),那麼,若要使用資料庫來進行存儲及讀取,該如何實現?
一、存儲

//第一步,將Drawable對象轉化為Bitmap對象

Bitmap bmp = (((BitmapDrawable)tmp.image).getBitmap());

//第二步,聲明並創建一個輸出位元組流對象

ByteArrayOutputStream os = new ByteArrayOutputStream();

//第三步,調用compress將Bitmap對象壓縮為PNG格式,第二個參數為PNG圖片質量,第三個參數為接收容器,即輸出位元組流os

bmp.compress(Bitmap.CompressFormat.PNG, 100, os);

//第四步,將輸出位元組流轉換為位元組數組,並直接進行存儲資料庫操作,注意,所對應的列的數據類型應該是BLOB類型

ContentValues values = new ContentValues();

values.put("image", os.toByteArray());

db.insert("apps", null, values);

db.close();

4. bitmap能存放的最大數據是多少

redis的bitmap能設置最大的長度是多少, 為什麼可以設置的最大長度位數是2^32, 怎麼計算bitmap會佔用多大的空間





前提: 實際上, redis只支持5種數據類型. 並沒有bitmap. 也就是bitmap是基於redis的字元串類型的. 而一個字元串類型最多存儲512M.


首先: 計算機的單位換算先了解下


8 bit = 1byte


1024 byte = 1kb


1024 kb = 1Mb


其次:


我們使用的bitmap指令SETBIT key offset value, 這個指令就是將第offset設置成0或1. 比如 SETBIT ss 1000 1 //就是將1000位置為1. 1 bit就是1位, 所以我們只要將512M換算成bit, 那麼就知道bitmap支持的最大設置長度了. 計算如下


8 * 1024 * 1024 * 512 = 2^32 (所以這個結果就是這么來的)



怎麼計算自己的bitmap會大概佔用多大的存儲空間呢?


舉個栗子: 今有一個bitmap最大長度1024, 需要佔用多大的空間?


解: 長度1024也就是他需要1024個位(bit), 或者單位為byte就是需要 1024 / 8, 即需要128byte

————————————————

版權聲明:本文為CSDN博主「Day____Day____Up」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/weixin_37281289/article/details/106834014

熱點內容
flashas編程 發布:2024-11-29 02:38:49 瀏覽:368
先編譯成什麼格式的文件 發布:2024-11-29 02:38:48 瀏覽:119
王者榮耀安卓q區哪個英雄好拿標 發布:2024-11-29 01:56:04 瀏覽:665
網易收件伺服器怎麼填寫 發布:2024-11-29 01:52:15 瀏覽:278
螢石攝像頭激活密碼是多少 發布:2024-11-29 01:51:38 瀏覽:579
iphone如何設置像安卓動態壁紙 發布:2024-11-29 01:37:50 瀏覽:474
電腦如何避過聯網查配置 發布:2024-11-29 01:25:16 瀏覽:972
期貨軟體編程 發布:2024-11-29 01:13:16 瀏覽:834
如何下載加密pdf文件 發布:2024-11-29 01:09:21 瀏覽:326
高通android開發 發布:2024-11-29 01:09:11 瀏覽:693