zoukankan      html  css  js  c++  java
  • Android高级之十二讲之如何降低应用内存消耗



    安卓应用的内存往往是有限的,从开始的8M到16M,24M,32M,48M,64M等逐步变大,但内存的变大是由于分辨率的提高导致,并不意味着可以随意声明使用内存,而不及时回收(即使Java有自己的垃圾回收机制,但内存过高会引起应用变卡,体验流畅性下降)。

    降低应用内存消耗的办法有以下几种常见办法:

    1、图片声明使用的context使用Application,回收时清除ImageView的drawable

    2、使用viewStub占位,避免经常使用gone方法,减少对象的加载和初始化

    3、使用merge把能合并的布局统统合并,在hierachyviewer里面可以看到布局的复杂度

    4、去掉decorView和window的背景,往往由于应用有自身的色调搭配

    5、通过canvas的clip方法,避免在看不到的地方画图,通过quickReject方法来在确定的区域比如矩形内绘制,

    跳过非既定区域内绘制

    6、使用9path文件和自定义图片,以及透明背景,来防止过度绘制

    7、列表可以给定一个高度(根据item的高度来动态设置),来防止重复计算高度和执行布局方法

    8、合理选择组件,选择简单的而非复杂的组件(原因,如果你自定义过复杂组件自己就会明白)

    9、开启新进程作为服务进程和工具进程-最大招,有效降低当前应用的内存消耗


    避免内存泄露的几个办法:

    1、及时清除对象或回调引用的context,降低引用链长度

        /**
         * 清除页面的ImageView的引用链
         * @param view
         */
        public static void unbindDrawables(View view) {
            if (view.getBackground() != null) {
                view.getBackground().setCallback(null);
            }
            if (view instanceof ViewGroup) {
                for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
                    unbindDrawables(((ViewGroup) view).getChildAt(i));
                }
                ((ViewGroup) view).removeAllViews();
            }
        }


    2、Bitmap用前根据屏幕dpi或自定义要求进行压缩,过后及时回收

    3、Cursor对象及时关闭,避免对数据库对象的长期引用

    4、关键地方做空判断,页面关闭时及时回收对象

    5、context尽量使用application,避免页面关闭时,由于引用存在而不能及时回收对象

    6、避免在for循环中声明对象(一下子无数个对象产生,内存暴增),引用能写在外面最好,如array.length,直接用

    int size获取值,再遍历

    7、打开开发者模式中的CPU绘制选项,根据屏幕显示的红黄蓝来辨别页面的绘制情况

    8、handler往往引用context,使用弱引用的方式处理

        public WeakHandler handler = new WeakHandler(this);
    
        public class WeakHandler extends Handler {
            WeakReference<Context> mContextWeakReference;
    
            public WeakHandler(Context context) {
                mContextWeakReference = new WeakReference<Context>(context);
            }
    
            @Override
            public void handleMessage(Message msg) {
                if (mContextWeakReference.get() == null || msg == null) {
                    return;
                }
                boolean handled = !handleMessageDelegate(msg.what, msg.obj);
                if (handled) {
                    if (msg.what < 0) {
                        handleErrorMessage(msg);
                    } else {
                        handlePtrMessage(msg);
                    }
                }
            }
        }

    9、一般webView也会有内存泄露的问题出现,往往由于引用未删除,自身的view仍然存在,在进程一系列操作后,仍可以使用开启新进程来降低应用内存

        /**
         * 优化内存最后一招-开启新进程
         */
        @Override
        protected void onDestroy() {
            if (mWebView != null) {// remove webView, prevent chromium to crash
                ViewParent parent = mWebView.getParent();
                if (parent != null) {
                    ((ViewGroup) parent).removeView(mWebView);
                }
                // 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错
                mWebView.getSettings().setJavaScriptEnabled(false);
                // 解决Receiver not registered:
                // android.widget.ZoomButtonsController
                mWebView.setVisibility(View.GONE);
                mWebView.removeAllViews();
                mWebView.clearCache(false);
                mWebView.stopLoading();
                mWebView.destroy();
                mWebView = null;
                setConfigCallback(null);
            }
            super.onDestroy();
        }
    
        /**
         * 删除引用
         * @param windowManager
         */
        public void setConfigCallback(WindowManager windowManager) {
            try {
                Field field = WebView.class.getDeclaredField("mWebViewCore");
                field = field.getType().getDeclaredField("mBrowserFrame");
                field = field.getType().getDeclaredField("sConfigCallback");
                field.setAccessible(true);
                Object configCallback = field.get(null);
                if (null == configCallback) {
                    return;
                }
                field = field.getType().getDeclaredField("mWindowManager");
                field.setAccessible(true);
                field.set(configCallback, windowManager);
            } catch(Exception e) {
            }
        }


    检查内存泄露的工具有:Lint(inspect code-performance)、Mat(case gc-分析hprof文件)、LeakMemory(Log日志弹窗)、As自带(Monitor-Dump Java Heap),更多介绍

    图片更多:Android ImageView设置图片原理(下)



  • 相关阅读:
    (最小路径覆盖) poj 1422
    (匈牙利算法) hdu 2119
    (匈牙利算法) hdu 4185
    (匈牙利算法) hdu 2063
    (匈牙利算法)hdu 1281
    (匈牙利算法DFS)hdu 3729
    (01 染色判奇环) hdu 3478
    (多重背包)poj 1276
    (判断欧拉回路)poj 1368
    (差分约束) hdu 1384
  • 原文地址:https://www.cnblogs.com/fengju/p/6174375.html
Copyright © 2011-2022 走看看