内存硬件发展
由于咱们的技术分享要结合Android和IOS两端来进行,所以本次分享大部分内容将围绕着一些硬件的发展以及关于图片内存使用来进行,其中可能会涉及到一些Android图片内存使用的东西,如果有问题大家可以随时打断我进行探讨。
随着手机硬件技术的发展,内存硬件不论是在空间上还是在读写速度上都有了很大的提升,Facebook 有一个叫device-year-class的开源库,它会用年份来区分设备的性能。可以看到,2008 年的手机只有可怜的 140MB 内存,而今年的华为 Mate 40 Pro 手机的内存已经达到了 8GB。
在读写速度方面,手机内存与PC内存不同,其采用的是LPDDR RAM,全称是“低功率双倍数据速率内存”,其中LP(Lower Power)就是低功耗的意思。以LPDDR4为例,带宽 = 时钟频率 × 内存总线位数 ÷ 8,即 1600 × 64 ÷ 8 = 12.8GB/s,因为是 DDR 内存是双倍速率,所以最后的带宽是 12.8 × 2 = 25.6GB/s。
上图可以看出LPDDR4的性能要比LPDDR3高出一倍,并且LPDDR4X的工作电压比LPDDR4的电压更低,可以节省电量20%~40%。以上可以看出手机内存并不是越大越好,还要考虑读写速度问题,一个LPDDR4X的4GB内存手机在运行方面会比LPDDR3的6GB手机更加实用。但是内存并不是一个孤立的概念,也需要结合操作系统、应用生态等因素。使用 Android 9.0 系统会比 Android 4.0 系统流畅,使用更加封闭、规范的 iOS 系统也会比“狂野”的 Android 系统更好。
Bitmap优化基础
在手机内存使用中,图片的使用时比较耗费内存空间的一方面。
从本地加载或者从网络加载可以用下面的公式计算
图片的长度 * 图片的宽度 * 一个像素点占用的字节数
以上公式可以看出在内存使用过程中对Bitmap进行简单优化可以从图片大小以及单个像素点占用的字节数两方面进行。
首先我们先从Bitmap的大小进行优化
顾名思义,图片的大小就是bitmap的宽高,按公式我们可以缩减bitmap的宽高来达到压缩图片占用内存的目的。BitmapFactory 类提供了几种用于从各种来源创建 Bitmap 的解码方法(decodeByteArray()、decodeFile()、decodeResource() 等)。根据您的图片数据源选择最合适的解码方法。这些方法尝试为构造的位图分配内存,因此很容易导致 OutOfMemory 异常。每种类型的解码方法都有额外的签名,允许您通过 BitmapFactory.Options 类指定解码选项。在解码时将 inJustDecodeBounds 属性设置为 true 可避免内存分配,为位图对象返回 null,但设置 outWidth、outHeight 和 outMimeType。此方法可让您在构造位图并为其分配内存之前读取图片数据的尺寸和类型。
看下面代码,以缩减宽高来达到压缩的目的
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(photoPath, options);
//图片的宽高
int outHeight = options.outHeight;
int outWidth = options.outWidth;
Log.d("bitmap", "图片宽=" + outWidth + "图片高=" + outHeight);
//计算采样率
int i = utils.calculateInSampleSize(options, 1000 * 1000);
//设置采样率,不能小于1 假如是2 则宽为之前的1/2,高为之前的1/2,一共缩小1/4 一次类推
options.inSampleSize = i;
Log.d("bitmap", "采样率为=" + i);
//图片格式压缩
//options.inPreferredConfig = Bitmap.Config.RGB_8888;
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(photoPath, options);
float bitmapsize = getBitmapsize(bitmap);
Log.d("bitmap","压缩后:图片占内存大小" + bitmapsize + "MB / 宽度=" +
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;
}
看下打印信息
09-09 11:02:11.714 8010-8010/com.example.chinaso.demo D/bitmap: 原图:图片占内存大小=45.776367MB / 宽度=4000高度=3000
09-09 11:02:11.715 8010-8010/com.example.chinaso.demo D/bitmap: 图片宽=4000图片高=3000
09-09 11:02:11.715 8010-8010/com.example.chinaso.demo D/bitmap: 采样率为=4
09-09 11:02:11.944 8010-8010/com.example.chinaso.demo D/bitmap: 压缩后:图片占内存大小2.859375MB / 宽度=1000高度=750
这种我们根据BitmapFactory 的采样率进行压缩 设置采样率,不能小于1 假如是4 则宽为之前的1/4,高为之前的1/4,一共缩小1/16以此类推,我们看到log ,确实起到了压缩的目的
其次我们从Bitmap编码方面入手
Android为我们提供了4种编码格式:
其中,A代表透明度;R代表红色;G代表绿色;B代表蓝色。
ALPHA_8<