android性能优化之内存优化

2019-01-02  本文已影响0人  Peakmain

android的内存管理机制

内存分配机制

进程优先级

1.前台进程,可见进程,服务进程,后台进程,空进程
2.android会将进程评定为它可能会达到的最高级别

回收效益:android总是会倾向于杀死一个能回收更多内存的进程

java的引用方式

1.强引用

2.软引用

例:SoftReference aSoftRef=new SoftReference (aRef)

3.弱引用

例:WeaiReference <data> ref=new WeaiReference <data>(new data);

4.虚引用

例:ReferenceQueue <String> queue=new ReferenceQueue <String>();
PhantomReference<String>pr=new PhantomReference<String>(new String("peakmain"),queue);

内存泄露

指由于错误或疏忽造成程序未能释放已经不再使用的内存

内存抖动

指内存频繁地分配和回收

内存抖动的后果

解决方案

内存溢出

应用申请超过最大内存空间

产生原因

解决方案

图片优化

首先我们举个例子看下图片占用的内存的大小

  private final String path = "/sdcard/Download/image1.jpg";
    private void showSize() throws IOException {
        File file = new File(path);
        if (!file.exists()) {
            return;
        }
        FileInputStream fis = new FileInputStream(file);
        int size = fis.available();
        Log.e("TAG", "size=" + size);
        Bitmap bitmap= BitmapFactory.decodeStream(fis);
        Log.e("TAG", "bitmapsize=" + bitmap.getByteCount());
    }

我的图片的结果是

image.png
图片占用内存影响因素
图片的长度,图片的宽度,单位像素所占用的字节数

图片占用的内存=图片长度图片宽度单位像素所占用的字节数

关于图片压缩,Google提供中文文档:http://hukai.me/android-training-course-in-chinese/graphics/displaying-bitmaps/load-bitmap.html

 public  Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) {

        //加载图片信息,不加载图片
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        //BitmapFactory.decodeResource(res, resId, options);
        BitmapFactory.decodeFile(path,options);

        // 计算压缩比
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        Log.e("TAG","inSampleSize:"+ options.inSampleSize );
        // 加载图片到内存
        options.inJustDecodeBounds = false;
        //单位像素所占用的字节数
        options.inPreferredConfig= Bitmap.Config.RGB_565;
        return  BitmapFactory.decodeFile(path,options);
    }

    public  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;

  
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }
压缩前后结果对比.png

图片压缩的主要思路:

图片的局部显示

 private Bitmap decodeRegionBitmap(int offX) throws IOException {
        //获取图片的宽高信息
        BitmapFactory.Options options=new BitmapFactory.Options();
        options.inJustDecodeBounds=true;
        BitmapFactory.decodeFile(path,options);
        final int height = options.outHeight;
        final int width = options.outWidth;
        //设置图片局部显示的区域
        BitmapRegionDecoder bitmapRegionDecoder=BitmapRegionDecoder.newInstance(path,false);
        BitmapFactory.Options newOptions=new BitmapFactory.Options();
        newOptions.inPreferredConfig= Bitmap.Config.RGB_565;
        //加载局部图片
        Bitmap bitmap=bitmapRegionDecoder
                .decodeRegion(new Rect(0+offX,0,width/2+offX,height),newOptions);
        return bitmap;
    }

效果如下


效果图.gif

图片的内存缓存策略
三级缓存

缓存池特性:总有大小限制,能够智能化的回收移除池内一部分图片

缓存池的二级缓存

  //二级缓存
    HashMap<String, SoftReference<Bitmap>> mSecondCache = new HashMap<>();
    final int MAX_NUM = 10;
    //一级缓存:强应用缓存
    //最近访问量
    HashMap<String, Bitmap> mFirstCache = new LinkedHashMap<String, Bitmap>(MAX_NUM, 0.75f, true) {
        //移除最老的因素
        @Override
        protected boolean removeEldestEntry(Entry<String, Bitmap> eldest) {
            // return super.removeEldestEntry(eldest);
            if (size() > MAX_NUM) {
                mSecondCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
                return true;
            }
            return false;
        }
    };

软引用在缓存的处理上是没有效率的,因为效率比较低,所以一般情况下是可以取掉

数据结构优化

String StringBuilder StringBuffer三者的区别

 private void stringJoin() {
        long time1 = System.currentTimeMillis();
        String result = "";
        for (int i = 0; i <4000; i++) {
            result = result + data[i];
        }
        long time2 = System.currentTimeMillis();
        long time = time2 - time1;
        Log.e(TAG, "stringjoinTime:" + time);
    }

    private void stringBufferJoin() {
        long time1 = System.currentTimeMillis();
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < 4000; i++) {
            result.append(data[i]);
        }
        long time2 = System.currentTimeMillis();
        long time = time2 - time1;
        Log.e(TAG, "stringBufferJoinTime:" + time);
    }

    private void stringBuilderJoin() {
        long time1 = System.currentTimeMillis();
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < 4000; i++) {
            result.append(data[i]);
        }
        long time2 = System.currentTimeMillis();
        long time = time2 - time1;
        Log.e(TAG, "stringBuilderJoinTime:" + time);
    }
结果.png

HashMap

ArrayMap

SparseArray

代码优化

常见内存泄露场景

其他优化

上一篇 下一篇

猜你喜欢

热点阅读