当前位置:首页 » 存储配置 » 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

热点内容
我的世界安卓手机如何改成官服 发布:2024-11-29 02:43:11 浏览:290
域服务器如何进行管理 发布:2024-11-29 02:43:08 浏览:186
ftp失火 发布:2024-11-29 02:42:27 浏览:193
flashas编程 发布:2024-11-29 02:38:49 浏览:369
先编译成什么格式的文件 发布:2024-11-29 02:38:48 浏览:120
王者荣耀安卓q区哪个英雄好拿标 发布:2024-11-29 01:56:04 浏览:665
网易收件服务器怎么填写 发布:2024-11-29 01:52:15 浏览:279
萤石摄像头激活密码是多少 发布:2024-11-29 01:51:38 浏览:579
iphone如何设置像安卓动态壁纸 发布:2024-11-29 01:37:50 浏览:474
电脑如何避过联网查配置 发布:2024-11-29 01:25:16 浏览:972