美文网首页
内存优化

内存优化

作者: Method | 来源:发表于2021-05-31 19:13 被阅读0次

    OOM

    申请内存超过堆内存剩余空间的最大值

    内存抖动

    原因

    短时间大量的对象创建销毁,导致频繁的GC

    后果

    1.导致卡顿

    Gc过程会将所有的进程挂起,主线程如果被频繁的挂起就会导致卡顿


    ka.png

    2.OOM

    例如标记清除算法,会导致内存碎片,当需要一个较大的内连续存空间(为对象分配内存时会选择连续的内存),会出现OOM问题


    flagclear.png

    实例

    自定义view

    class ProgressView @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
    ) : View(context, attrs, defStyleAttr) {
    
        private var progress = 0f
            get() = field
            set(value) {
                field = value
                invalidate()
            }
        override fun onDraw(canvas: Canvas?) {
            super.onDraw(canvas)
            val paint = Paint()
            paint.strokeWidth =3.0f
            paint.isAntiAlias = true
            paint.isDither = true
    
            val path = Path()
            val path1 = Path()
            val path2 = Path()
            val path3 = Path()
        }
    
        fun startAnimation(){
            val objectAnimator = ObjectAnimator.ofFloat(this,"progress",1f,100f)
            objectAnimator.duration = 400
            objectAnimator.repeatCount = -1
            objectAnimator.start()
        }
    }
    

    查看内存使用

    doudong.png

    抖动原因

     override fun onDraw(canvas: Canvas?) {
            super.onDraw(canvas)
            val paint = Paint()
            paint.strokeWidth =3.0f
            paint.isAntiAlias = true
            paint.isDither = true
    
            val path = Path()
            val path1 = Path()
            val path2 = Path()
            val path3 = Path()
        }
    

    ondraw()中频繁的创建paint、path对象,导致内存中不停的创建销毁。所以要将对象的创建放在外面

    lateinit var paint:Paint
        lateinit var path:Path
        init {
            paint = Paint()
            path = Path()
        }
        override fun onDraw(canvas: Canvas?) {
            super.onDraw(canvas)
            paint.strokeWidth =3.0f
            paint.isAntiAlias = true
            paint.isDither = true
            path.lineTo(0f,0f)
            path.reset()
            path.moveTo(100f,100f)
        }
    
    after.png

    内存泄漏

    程序中动态分配的堆内存由于某种原因程序未释放,或者无法释放,造成内存的浪费。
    长生命周期强引用短生命周期对象,导致段短生命周期对象无法被回收!

    判断对象是否可回收

    > 可达性算法
    > 当一个对象到Gcroot对象的引用链不可达时,对象就可以被回收。否则不可回收
    > GCroot对象如静态变量
    

    内存泄漏常见案例

    单例导致的内存泄漏

    作为GCroot,持有短生命周期如activity引用,导致activity不能被回收

    public class Manager {
        //GcRoot
        private static Manager mManager = new Manager();
        private Context mContext;
    
        public static Manager getInstance() {
            return mManager;
        }
    
        public void init(Context context) {
            mContext = context;
        }
    }
    

    泄漏原因

    由于mManager持有context,mManager时静态的和app的生命周期一样长,所以导致Activity不能被释放

    解决方法

    传递application

     val instance = Manager.getInstance()
     instance.init(application)
    

    handler导致的内存泄漏(匿名内部类,非静态内部类)

    var i = 0
        fun text(){
            val handler = Handler(Looper.getMainLooper()!!)
            handler.postDelayed(object: Runnable{          
                override fun run() {
                    println("i==$i")
                }
            },100000)
        }
    

    泄漏原因

    Runnable是匿名内部类,会持有外部类的引用,runnable又会被封装到message,message会被放到消息队列中,如果消息没有被处理,引用不会被释放,导致activity不能被释放

    解决方法

    override fun onDestroy() {
            super.onDestroy()
            //activity 销毁时 清除消息
            handler.removeCallbacksAndMessages(null)
    }
    

    inner class MRunnable:Runnable{
            constructor(context: Context){
                //弱引用 当Gc时会被回收
                val weakReference = WeakReference(context)
            }
            override fun run() {
                println("i==$i")
            }
        }
    

    资源使用未关闭

     try {
        val stream = FileOutputStream("")
        stream.write("".toByteArray())
        stream.close()
     }catch (e:Exception){
        e.printStackTrace()
     }
    

    解决方法

    try {
                fos = FileOutputStream("")
                fos?.write("".toByteArray())
                fos?.close()
            }catch (e:Exception){
                e.printStackTrace()
            }finally {
                //需要防止异常情况 未关闭
                if(fos != null){
                    fos?.close()
                }
            }
    

    集合类

    当使用集合时只有添加元素,没有删除元素。如Eventbus只有注册没有注销

    工具分析

    dump内存

    dump.png

    分析内存中对象

    leak.png

    相关文章

      网友评论

          本文标题:内存优化

          本文链接:https://www.haomeiwen.com/subject/wrgbsltx.html