Android 图片内存优化与图片压缩
1. 对图片本身进行操作
尽量不要使用 setImageBitmap、setImageResource、 BitmapFactory.decodeResource 来设置一张大图,因为这些方法在完成 decode 后,最终都是通过 Java 层的 createBitmap 来完成的,需要消耗更多内存。因此,改用先通过 BitmapFactory.decodeStream 方法,创建出一个 bitmap,再将其设为 ImageView 的 source,decodeStream 最大的秘密在于其直接调用 JNI>>nativeDecodeAsset() 来完成 decode,无需再使用 Java 层的 createBitmap,从而节省了 Java 层的空间。如果在读取时加上图片的 Config 参数,可以更有效的减少加载的内存,从而更有效阻止抛出内存异常。另外,decodeStream 直接拿图片来读取字节码了,不会根据机器的各种分辨率来自动适应,使用了 decodeStream 之后,需要在 hdpi 和 mdpi,ldpi 中配置相应的图片资源, 否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。
InputStream is = this.getResources().openRawResource(R.drawable.pic);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 2;
Bitmap btp =BitmapFactory.decodeStream(is,null,options);
以上代码即是读取 drawable 下名为 pic 图片的缩略图,长度、宽度都只有原图片的 1/2。图片大小减少,占用的内存自然也变小了。这么做的弊端是图片质量变差,inSampleSize 的值越大,图片的质量就越差。由于各手机厂商缩放图片的算法不同,在不同手机上的缩放图片质量可能会不同。
2. 调用图片的 recycle() 方法
if(!bmp.isRecycle() ){
bmp.recycle() // 回收图片所占的内存
system.gc() // 提醒系统及时回收
}
这种方法其实不是真正降低图片内存的方法。主要目的是标记图片对象,方便回收图片对象的本地数据。图片对象的本地数据占用的内存最大,而且与程序 Java 部分的内存是分开计算的。所以经常出现 Java heap 足够使用,而图片发生 OutOfMemoryError 的情况。在图片不使用时调用该方法,可以有效降低图片本地数据的峰值,从而减少 OutOfMemoryError 的概率。不过调用了 recycle() 的图片对象处于“废弃”状态,调用时会造成程序错误。所以在无法保证该图片对象绝对不会被再次调用的情况下,不建议使用该方法。特别要注意已经用 setImageBitmap(Bitmap
img) 方法分配给控件的图片对象,可能会被系统类库调用,造成程序错误。
3. 以最省内存的方式读取本地资源的图片
/**
* 以最省内存的方式读取本地资源的图片
*/
public static Bitmap readBitMap(Context context, int resId){
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
// 获取资源图片
InputStream is = context.getResources().openRawResource(resId);
return BitmapFactory.decodeStream(is,null,opt);
}
Android 中加载图片的颜色模式有四种,分别是:ALPHA_8:每个像素占用 1byte 内存、ARGB_4444:每个像素占用 2byte 内存、ARGB_8888:每个像素占用 4byte 内存、RGB_565:每个像素占用 2byte 内存。Android默认的颜色模式为ARGB_8888,这个颜色模式色彩最细腻,显示质量最高。但同样的,占用的内存也最大。以上代码即是将图片资源以 RGB_565 (或以 ARGB_4444)模式读出。内存减少虽然不如第一种方法明显,但是对于大多数图片,看不出与 ARGB_8888 模式有什么差别。不过在读取有渐变效果的图片时,可能有颜色条出现。另外,会影响图片的特效处理。
4. 使用 Matrix 对象放大的图片如何更改颜色模式:
虽然使用 Matrix 对象放大图片,必定会耗费更多的内存,但有时候也不得不这样做。放大后的图片使用的 ARGB_8888 颜色模式,就算原图片是ARGB_4444 颜色模式也一样,而且没有办法在放大时直接指定颜色模式。可以采用以下办法更改图片颜色模式。
Matrix matrix = new Matrix();
float newWidth = 200; // 图片放大后的宽度
float newHeight = 300; // 图片放大后的长度
matrix.postScale(newWidth / img.getWidth(), newHeight/ img.getHeight());
Bitmap img1 = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);// 得到放大图片
img2 = img1.copy(Bitmap.Config.ARGB_4444, false); // 得到 ARGB_4444 颜色模式的图片
img = null;
img1 = null;
这里比起本来的图片额外生成了一个图片对象 img1。然则体系会主动收受接管 img1,所以实际内存还是削减了。
归结起来还是以缩略图模式读取图片和削减图片中每个像素占用的内存最为有效。 这两种办法固然有效,然则也有各自的弊病。实际开辟中还是应当按照景象酌情应用。最王道的办法,还是避免垃圾对象的产生。例如在 ListView 的应用中,复用 convertView 等。若是应用 AsyncTask 加载图片,要及时将引用的 ImageView 对象置为 null。因为 AsyncTask 是用线程池实现的,所以此中引用的对象可能会拥有很长的生命周期,造成 GC 无法开释。我还是信赖 Android 的内存收受接管机制的,recycle 什么的固然必然程度上有效,但总感觉不合适 Java 内存收受接管的原则。
两种方法都实装在了我的项目中,结果却发现在质量压缩的模块中,本来1.9M的图片压缩后反而变成3M多了,很是奇怪,再做了进一步调查终于知道原因了。下面这个博客说的比较清晰:
android图片压缩总结
总结来看,图片有三种存在形式:硬盘上时是file,网络传输时是stream,内存中是stream或bitmap,所谓的质量压缩,它其实只能实现对file的影响,你可以把一个file转成bitmap再转成file,或者直接将一个bitmap转成file时,这个最终的file是被压缩过的,但是中间的bitmap并没有被压缩(或者说几乎没有被压缩,我不确定),因为bigmap在内存中的大小是按像素计算的,也就是width * height,对于质量压缩,并不会改变图片的像素,所以就算质量被压缩了,但是bitmap在内存的占有率还是没变小,但你做成file时,它确实变小了;
而尺寸压缩由于是减小了图片的像素,所以它直接对bitmap产生了影响,当然最终的file也是相对的变小了;
最后把自己总结的工具类贴出来:
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import android.graphics.Bitmap;
- import android.graphics.Bitmap.Config;
- import android.graphics.BitmapFactory;
- /**
- * Image compress factory class
- *
- * @author
- *
- */
- public class ImageFactory {
- /**
- * Get bitmap from specified image path
- *
- * @param imgPath
- * @return
- */
- public Bitmap getBitmap(String imgPath) {
- // Get bitmap through image path
- BitmapFactory.Options newOpts = new BitmapFactory.Options();
- newOpts.inJustDecodeBounds = false;
- newOpts.inPurgeable = true;
- newOpts.inInputShareable = true;
- // Do not compress
- newOpts.inSampleSize = 1;
- newOpts.inPreferredConfig = Config.RGB_565;
- return BitmapFactory.decodeFile(imgPath, newOpts);
- }
- /**
- * Store bitmap into specified image path
- *
- * @param bitmap
- * @param outPath
- * @throws FileNotFoundException
- */
- public void storeImage(Bitmap bitmap, String outPath) throws FileNotFoundException {
- FileOutputStream os = new FileOutputStream(outPath);
- bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
- }
- /**
- * Compress image by pixel, this will modify image width/height.
- * Used to get thumbnail
- *
- * @param imgPath image path
- * @param pixelW target pixel of width
- * @param pixelH target pixel of height
- * @return
- */
- public Bitmap ratio(String imgPath, float pixelW, float pixelH) {
- BitmapFactory.Options newOpts = new BitmapFactory.Options();
- // 开始读入图片,此时把options.inJustDecodeBounds 设回true,即只读边不读内容
- newOpts.inJustDecodeBounds = true;
- newOpts.inPreferredConfig = Config.RGB_565;
- // Get bitmap info, but notice that bitmap is null now
- Bitmap bitmap = BitmapFactory.decodeFile(imgPath,newOpts);
- newOpts.inJustDecodeBounds = false;
- int w = newOpts.outWidth;
- int h = newOpts.outHeight;
- // 想要缩放的目标尺寸
- float hh = pixelH;// 设置高度为240f时,可以明显看到图片缩小了
- float ww = pixelW;// 设置宽度为120f,可以明显看到图片缩小了
- // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
- int be = 1;//be=1表示不缩放
- if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
- be = (int) (newOpts.outWidth / ww);
- } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
- be = (int) (newOpts.outHeight / hh);
- }
- if (be <= 0) be = 1;
- newOpts.inSampleSize = be;//设置缩放比例
- // 开始压缩图片,注意此时已经把options.inJustDecodeBounds 设回false了
- bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
- // 压缩好比例大小后再进行质量压缩
- // return compress(bitmap, maxSize); // 这里再进行质量压缩的意义不大,反而耗资源,删除
- return bitmap;
- }
- /**
- * Compress image by size, this will modify image width/height.
- * Used to get thumbnail
- *
- * @param image
- * @param pixelW target pixel of width
- * @param pixelH target pixel of height
- * @return
- */
- public Bitmap ratio(Bitmap image, float pixelW, float pixelH) {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- image.compress(Bitmap.CompressFormat.JPEG, 100, os);
- if( os.toByteArray().length / 1024>1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
- os.reset();//重置baos即清空baos
- image.compress(Bitmap.CompressFormat.JPEG, 50, os);//这里压缩50%,把压缩后的数据存放到baos中
- }
- ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
- BitmapFactory.Options newOpts = new BitmapFactory.Options();
- //开始读入图片,此时把options.inJustDecodeBounds 设回true了
- newOpts.inJustDecodeBounds = true;
- newOpts.inPreferredConfig = Config.RGB_565;
- Bitmap bitmap = BitmapFactory.decodeStream(is, null, newOpts);
- newOpts.inJustDecodeBounds = false;
- int w = newOpts.outWidth;
- int h = newOpts.outHeight;
- float hh = pixelH;// 设置高度为240f时,可以明显看到图片缩小了
- float ww = pixelW;// 设置宽度为120f,可以明显看到图片缩小了
- //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
- int be = 1;//be=1表示不缩放
- if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
- be = (int) (newOpts.outWidth / ww);
- } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
- be = (int) (newOpts.outHeight / hh);
- }
- if (be <= 0) be = 1;
- newOpts.inSampleSize = be;//设置缩放比例
- //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
- is = new ByteArrayInputStream(os.toByteArray());
- bitmap = BitmapFactory.decodeStream(is, null, newOpts);
- //压缩好比例大小后再进行质量压缩
- // return compress(bitmap, maxSize); // 这里再进行质量压缩的意义不大,反而耗资源,删除
- return bitmap;
- }
- /**
- * Compress by quality, and generate image to the path specified
- *
- * @param image
- * @param outPath
- * @param maxSize target will be compressed to be smaller than this size.(kb)
- * @throws IOException
- */
- public void compressAndGenImage(Bitmap image, String outPath, int maxSize) throws IOException {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- // scale
- int options = 100;
- // Store the bitmap into output stream(no compress)
- image.compress(Bitmap.CompressFormat.JPEG, options, os);
- // Compress by loop
- while ( os.toByteArray().length / 1024 > maxSize) {
- // Clean up os
- os.reset();
- // interval 10
- options -= 10;
- image.compress(Bitmap.CompressFormat.JPEG, options, os);
- }
- // Generate compressed image file
- FileOutputStream fos = new FileOutputStream(outPath);
- fos.write(os.toByteArray());
- fos.flush();
- fos.close();
- }
- /**
- * Compress by quality, and generate image to the path specified
- *
- * @param imgPath
- * @param outPath
- * @param maxSize target will be compressed to be smaller than this size.(kb)
- * @param needsDelete Whether delete original file after compress
- * @throws IOException
- */
- public void compressAndGenImage(String imgPath, String outPath, int maxSize, boolean needsDelete) throws IOException {
- compressAndGenImage(getBitmap(imgPath), outPath, maxSize);
- // Delete original file
- if (needsDelete) {
- File file = new File (imgPath);
- if (file.exists()) {
- file.delete();
- }
- }
- }
- /**
- * Ratio and generate thumb to the path specified
- *
- * @param image
- * @param outPath
- * @param pixelW target pixel of width
- * @param pixelH target pixel of height
- * @throws FileNotFoundException
- */
- public void ratioAndGenThumb(Bitmap image, String outPath, float pixelW, float pixelH) throws FileNotFoundException {
- Bitmap bitmap = ratio(image, pixelW, pixelH);
- storeImage( bitmap, outPath);
- }
- /**
- * Ratio and generate thumb to the path specified
- *
- * @param image
- * @param outPath
- * @param pixelW target pixel of width
- * @param pixelH target pixel of height
- * @param needsDelete Whether delete original file after compress
- * @throws FileNotFoundException
- */
- public void ratioAndGenThumb(String imgPath, String outPath, float pixelW, float pixelH, boolean needsDelete) throws FileNotFoundException {
- Bitmap bitmap = ratio(imgPath, pixelW, pixelH);
- storeImage( bitmap, outPath);
- // Delete original file
- if (needsDelete) {
- File file = new File (imgPath);
- if (file.exists()) {
- file.delete();
- }
- }
- }
- }
- /**
- * 质量压缩方法
- *
- * @param image
- * @return
- */
- public static Bitmap compressImage(Bitmap image) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
- int options = 90;
- while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
- baos.reset(); // 重置baos即清空baos
- image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
- options -= 10;// 每次都减少10
- }
- ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
- Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
- return bitmap;
- }
二、按比例大小压缩 (路径获取图片)
- /**
- * 图片按比例大小压缩方法
- *
- * @param srcPath (根据路径获取图片并压缩)
- * @return
- */
- public static Bitmap getimage(String srcPath) {
- BitmapFactory.Options newOpts = new BitmapFactory.Options();
- // 开始读入图片,此时把options.inJustDecodeBounds 设回true了
- newOpts.inJustDecodeBounds = true;
- Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此时返回bm为空
- newOpts.inJustDecodeBounds = false;
- int w = newOpts.outWidth;
- int h = newOpts.outHeight;
- // 现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
- float hh = 800f;// 这里设置高度为800f
- float ww = 480f;// 这里设置宽度为480f
- // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
- int be = 1;// be=1表示不缩放
- if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
- be = (int) (newOpts.outWidth / ww);
- } else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放
- be = (int) (newOpts.outHeight / hh);
- }
- if (be <= 0)
- be = 1;
- newOpts.inSampleSize = be;// 设置缩放比例
- // 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
- bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
- return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩
- }
三、按比例大小压缩 (Bitmap)
- /**
- * 图片按比例大小压缩方法
- *
- * @param image (根据Bitmap图片压缩)
- * @return
- */
- public static Bitmap compressScale(Bitmap image) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
- // 判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
- if (baos.toByteArray().length / 1024 > 1024) {
- baos.reset();// 重置baos即清空baos
- image.compress(Bitmap.CompressFormat.JPEG, 80, baos);// 这里压缩50%,把压缩后的数据存放到baos中
- }
- ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
- BitmapFactory.Options newOpts = new BitmapFactory.Options();
- // 开始读入图片,此时把options.inJustDecodeBounds 设回true了
- newOpts.inJustDecodeBounds = true;
- Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
- newOpts.inJustDecodeBounds = false;
- int w = newOpts.outWidth;
- int h = newOpts.outHeight;
- Log.i(TAG, w + "---------------" + h);
- // 现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
- // float hh = 800f;// 这里设置高度为800f
- // float ww = 480f;// 这里设置宽度为480f
- float hh = 512f;
- float ww = 512f;
- // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
- int be = 1;// be=1表示不缩放
- if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
- be = (int) (newOpts.outWidth / ww);
- } else if (w < h && h > hh) { // 如果高度高的话根据高度固定大小缩放
- be = (int) (newOpts.outHeight / hh);
- }
- if (be <= 0)
- be = 1;
- newOpts.inSampleSize = be; // 设置缩放比例
- // newOpts.inPreferredConfig = Config.RGB_565;//降低图片从ARGB888到RGB565
- // 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
- isBm = new ByteArrayInputStream(baos.toByteArray());
- bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
- return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩
- //return bitmap;
- }
- public static void compressPicture(String srcPath, String desPath) {
- FileOutputStream fos = null;
- BitmapFactory.Options op = new BitmapFactory.Options();
- // 开始读入图片,此时把options.inJustDecodeBounds 设回true了
- op.inJustDecodeBounds = true;
- Bitmap bitmap = BitmapFactory.decodeFile(srcPath, op);
- op.inJustDecodeBounds = false;
- // 缩放图片的尺寸
- float w = op.outWidth;
- float h = op.outHeight;
- float hh = 1024f;//
- float ww = 1024f;//
- // 最长宽度或高度1024
- float be = 1.0f;
- if (w > h && w > ww) {
- be = (float) (w / ww);
- } else if (w < h && h > hh) {
- be = (float) (h / hh);
- }
- if (be <= 0) {
- be = 1.0f;
- }
- op.inSampleSize = (int) be;// 设置缩放比例,这个数字越大,图片大小越小.
- // 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
- bitmap = BitmapFactory.decodeFile(srcPath, op);
- int desWidth = (int) (w / be);
- int desHeight = (int) (h / be);
- bitmap = Bitmap.createScaledBitmap(bitmap, desWidth, desHeight, true);
- try {
- fos = new FileOutputStream(desPath);
- if (bitmap != null) {
- bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- }
需要注意两个问题:
一、调用getDrawingCache()前先要测量,否则的话得到的bitmap为null,这个我在OnCreate()、OnStart()、OnResume()方法里都试验过。
二、当调用bitmap.compress(CompressFormat.JPEG, 100, fos);保存为图片时发现图片背景为黑色,如下图:
这时只需要改成用png保存就可以了,bitmap.compress(CompressFormat.PNG, 100, fos);,如下图:
在实际开发中,有时候我们需求将文件转换为字符串,然后作为参数进行上传。
必备工具类图片bitmap转成字符串string与String字符串转换为bitmap图片格式
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.util.Base64;
- import java.io.ByteArrayOutputStream;
- /**
- *
- *
- * 功能描述:Android开发之常用必备工具类图片bitmap转成字符串string与String字符串转换为bitmap图片格式
- */
- public class BitmapAndStringUtils {
- /**
- * 图片转成string
- *
- * @param bitmap
- * @return
- */
- public static String convertIconToString(Bitmap bitmap)
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();// outputstream
- bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
- byte[] appicon = baos.toByteArray();// 转为byte数组
- return Base64.encodeToString(appicon, Base64.DEFAULT);
- }
- /**
- * string转成bitmap
- *
- * @param st
- */
- public static Bitmap convertStringToIcon(String st)
- {
- // OutputStream out;
- Bitmap bitmap = null;
- try
- {
- // out = new FileOutputStream("/sdcard/aa.jpg");
- byte[] bitmapArray;
- bitmapArray = Base64.decode(st, Base64.DEFAULT);
- bitmap =
- BitmapFactory.decodeByteArray(bitmapArray, 0,
- bitmapArray.length);
- // bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
- return bitmap;
- }
- catch (Exception e)
- {
- return null;
- }
- }
- }
如果你的图片是File文件,可以用下面代码:
- /**
- * 图片文件转换为指定编码的字符串
- *
- * @param imgFile 图片文件
- */
- public static String file2String(File imgFile) {
- InputStream in = null;
- byte[] data = null;
- //读取图片字节数组
- try{
- in = new FileInputStream(imgFile);
- data = new byte[in.available()];
- in.read(data);
- in.close();
- } catch (IOException e){
- e.printStackTrace();
- }
- //对字节数组Base64编码
- BASE64Encoder encoder = new BASE64Encoder();
- String result = encoder.encode(data);
- return result;//返回Base64编码过的字节数组字符串
- }
Android 图片内存优化与图片压缩的更多相关文章
- Android APP内存优化之图片优化
网上有很多大拿分享的关于Android性能优化的文章,主要是通过各种工具分析,使用合理的技巧优化APP的体验,提升APP的流畅度,但关于内存优化的文章很少有看到.在Android设备内存动不动就上G的 ...
- Android高效内存:让图片占用尽可能少的内存
Android高效内存:让图片占用尽可能少的内存 一.让你的图片最小化 1.1 大图小图内存使用情况对比 大图:440 * 336 小图:220 * 168 小图的高宽都是大图的1/2--> ...
- Android代码内存优化建议-OnTrimMemory优化
原文 http://androidperformance.com/2015/07/20/Android代码内存优化建议-OnTrimMemory优化/ OnTrimMemory 回调是 Androi ...
- Android的内存优化
腾讯公司在五月三十一日开展[腾讯Bugly移动开发人员沙龙]大会.大会上面叶方正老师解说了 关于Android的内存优化的问题,只是我感觉叶老师许多其它的站在了測试的角度上去解释了这一方面,叶老师给我 ...
- android内存优化之图片压缩和缓存
由于手机内存的限制和网络流量的费用现在,我们在加载图片的时候,必须要做好图片的压缩和缓存. 图片缓存机制一般有2种,软引用和内存缓存技术. 1.压缩图片:压缩图片要既不能模糊,也不能拉伸图片. 图片操 ...
- Android开发——内存优化 图片处理
8. 用缓存避免内存泄漏 很常见的一个例子就是图片的三级缓存结构,分别为网络缓存,本地缓存以及内存缓存.在内存缓存逻辑类中,通常会定义这样的集合类. private HashMap<Strin ...
- ANDROID开发之OOM:一张图片(BitMap)占用内存的计算 图片内存优化
Android中一张图片(BitMap)占用的内存主要和以下几个因数有关:图片长度,图片宽度,单位像素占用的字节数. 一张图片(BitMap)占用的内存=图片长度*图片宽度*单位像素占用的字节数 注: ...
- (Android图片内存优化)Picasso加载图片 教程。。详细版
Picasso 是 Android 上一个强大的图片下载和缓存库. 示例代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Picasso.with( ...
- UIImage 读取图片内存优化
在图片处理时,我们总会遇到一些内存优化的问题. 这里介绍的是其中一种内存优化处理方式. 场景: App 运行很卡,然后我用 Instruments 中的相关工具查看对象的内存占用情况,发现当图片加载 ...
随机推荐
- ubuntu修改apt源
1.修改之前首先做好备份 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak 2.编辑源列表文件 sudo vim /etc/apt/sou ...
- TensorFlow入门——安装
由于实验室新配了电脑,旧的电脑就淘汰下来不用,闲来无事,就讲旧的电脑作为个人的工作站来使用. 由于在旧电脑上安装的是Ubuntu 16.04 64bit系统,系统自带的是Python 2.7,版本选择 ...
- 完美解决Mysql的Access denied for user 'root'@'%的'问题
背景:mysql5.6 root已授权所有数据库,执行过下面的语句 grant all privileges on *.* to 'root'@'%' identified by 'root' 当使用 ...
- python 教程(一)
必须感慨一下,整了一周多的时间才基本理通顺.自己老是不能静心,方法也不对所以走了很多弯路. 1.建议:一定要先去看官方文档. 下面我们来看一周的成果吧: windows下如何下载并安装Python 3 ...
- 标准C语言(3)
操作符用来描述对数字的处理规则根据操作符所需要配合的数字个数把操作符分为单目操作符,双目操作符和三目操作符 C语言里用+,-,*和/表示加减乘除四则运算,它们都是双目操作符,如果参与除法计算的两个数字 ...
- Vue多页面 按钮级别权限控制 directive指令控制
利用driective 构建自己的指令,实现按钮级别权限 项目结构如下: 修改router.js { path: 'schools', name: '列表', component: () => ...
- 高性能mysql 第6章 查询性能优化
查询缓存: 在解析一个sql之前,如果查询缓存是打开的,mysql会去检查这个查询(根据sql的hash作为key)是否存在缓存中,如果命中的话,那么这个sql将会在解析,生成执行计划之前返回结果. ...
- 构建的Web应用界面不够好看?快试试最新的Kendo UI R3 2019
通过70多个可自定义的UI组件,Kendo UI可以创建数据丰富的桌面.平板和移动Web应用程序.通过响应式的布局.强大的数据绑定.跨浏览器兼容性和即时使用的主题,Kendo UI将开发时间加快了50 ...
- Ubuntu 安装matlab2013b
下载软件包: 链接:http://pan.baidu.com/s/1bHoFHc 密码:lugc 还要注意软件的解压的问题: 链接:http://pan.baidu.com/s/1geBEQyf 密码 ...
- vue cli3 项目配置
[转]https://juejin.im/post/5c63afd56fb9a049b41cf5f4 基于vue-cli3.0快速构建vue项目 本章详细介绍使用vue-cli3.0来搭建项目. 本章 ...