Android MVP (three) memory leak analysis and dynamic agent

Bloggers statement:

Please reprint this article at the beginning of additional links and author information, and marked as reserved. This article by the blogger  Whiskers Meow  original audience for support and advice.

This article first appeared in this    blogger : Whiskers Meow   |   blog home page : https://blog.csdn.net/smile_running

 

MVP architecture series:

Android MVP architecture (a) MVP architecture introduced with actual use

Android MVP architecture (two) BaseMVP MVP of the basic framework design

Memory leak analysis Android MVP MVP architecture (three) with dynamic proxies

Android MVP architecture (four) MVP generic configuration Model

Android MVP Architecture (e) a plurality of the MVP dependency injection Presenter

BaseFragment the Android MVP Architecture (six) of the MVP package

Android MVP architecture (seven) MVP of the proxy mode to eliminate duplication of code (End)

Source Address:

github Download: MVPDemo

csdn Download: MVPDemo

    Previous Article ( Android MVP architecture (two) BaseMVP MVP of the basic framework design ), we talked about how to package a BaseMVP base class, use this template, we can avoid a lot of repetitive code, and write the necessary treatment, to avoid leakage occurs write errors, and write the same code more certainly annoying. However, from BaseMVP package Part of the article point of view, there are still some shortcomings, such as the problem will not cause a memory leak? For example, when the method of the View layer of each call, have to judge the View layer is not destroyed, it is not as the case of NULL. In view of these two issues, we will carry out this analysis and solutions for both problems.

  • Memory Leak

    The first question: Will cause memory leak?

    This problem involves the issue of memory leaks, then take a look at what memory leaks is not it! GC (garbage collector) in Java is to recover those objects has been useless, the memory has been freed object, because this is the Java garbage collection mechanism, so we do not need to manually release the object reference memory. I believe we have learned in the university C, C ++ language, it would certainly have been reluctant in the pointer there. Every time we need to open up some memory by reference objects in memory to store address pointers, and when finished using the pointer object, you must manually set it to null operations. And yet in Java GC has helped us to do this work, but then, GC in fact, is not so omnipotent, it is to be controlled by some of the algorithms cited recovery, then we should go for recycling algorithm GC and principle.

    Having said that, you should have a roughly understand, a memory leak when the GC is to recover, however, these objects have not been released, or are other references to, in this case GC is not automatically recover, and this block has been occupied by the memory will be, is not released, which is the basic concept of memory leaks. However, such a situation the program rises, the program will Caton, Ben collapse, unusual phenomena reported when these objects occupy memory reaches a certain threshold, the machine is no extra memory is available, then you go to application memory space, OOM (out of memory) occurs. Therefore, a memory leak is a security risk, which directly affects the performance of the program. To do well in this regard, which requires an in-depth study.

    Not much nonsense, and we continue to look at the issue. BaseMVP actually cause a major security risk memory leaks, it's a memory leak from the View layer between the strong and the Presenter layer reference relationship. We direct binding layer in Presenter View before they can get a quote View layer, is a strong reference to the relationship between them, if not unbundling, then it will cause a memory leak occurs. Why will not understand tied a memory leak it? Let's look at the code:

public abstract class BasePresenter<V extends IBaseView> implements IBasePresenter {
    protected V mView;

    @SuppressWarnings("unchecked")
    @Override
    public void attech(IBaseView view) {
        mView = (V) view;
    }

    @Override
    public void detech() {
//        mView = null;
    }
}

    Here, we understand tie View, which is mView = null commented, means also holds a reference to Presenter View layer, was closed when the Activity, Activity equivalent to the View layer, due to the Activity Presenter layer or be quoted, when GC came, it looked Activity is referenced, it would not have to reclaim it. When you open and close again Activity, Activity and apply some new memory space, GC powerless to reclaim it, over time, it is bound to run out of memory.

    And here the blank will not cause a memory leak, because at this time of View, which is Activity references are released, and if no other references to the Activity object class time, when the GC to find Activity can be recycled and put it recovered off, this memory space is released.

    Having said that, in fact, is to introduce a memory leak problems write our own BaseMVP, the code here is based on an MVP v2 modified version, because it is a strong reference between V and P, so we changed to the soft referenced manner, OOM avoiding memory leaks due to take place. The code I did a little minor modifications, as follows:

BasePresenter modified base class:

package com.test.mvp.mvpdemo.mvp.v3.basemvp;

import java.lang.ref.SoftReference;

public abstract class BasePresenter<V extends IBaseView> implements IBasePresenter {
    private SoftReference<IBaseView> mReferenceView;

    @SuppressWarnings("unchecked")
    @Override
    public void attech(IBaseView view) {
        mReferenceView = new SoftReference<>(view);
    }

    @SuppressWarnings("unchecked")
    public V getView() {
        return (V) mReferenceView.get();
    }

    @Override
    public void detech() {
        mReferenceView.clear();
        mReferenceView = null;
    }
}

    Use a soft way to make cited references V P layer hold layer, and provides getView () method to call the P layer, the parent View variable privatization, to prevent its subclasses changes caused by other errors. Our Activity MainPresenter get references can be used getView () method to obtain. Soft citations insufficient memory down under, GC will prioritize the release of those objects to recover soft reference by reference, to a certain extent up to avoid running out of memory (OOM).

  • Dynamic Proxy

The second problem: every time let View short judgment, bored?

/**
 * presenter 层,承担业务逻辑处理,数据源处理等
 */
public class MainPresenter extends BasePresenter<MainContract.IMainView> implements MainContract.IMainPresenter {

    private MainContract.IMainModel mModel;

    @Override
    public void attech(IBaseView view) {
        super.attech(view);
        mModel = new DataModel();
    }

    @Override
    public void handlerData() {
        if (getView() != null) {
            getView().showDialog();
        }

        mModel.requestBaidu(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String content = response.body().string();
                if (getView() != null) {
                    getView().succes(content);
                }
            }
        });
    }

    @Override
    public void detech() {
        super.detech();
        /**
         * 释放内存、关闭网络请求、关闭线程等操作
         */
        Log.d("==========", "detech: 解除绑定,释放内存");
    }
}

    Why use a dynamic proxy it? We see above getView () code no time is required to determine the type of null, is not very difficult, but also because there is an interface of type View (V extends IBaseView) generic interface, this easy to handle, fully dynamic proxies can be done to determine the type of uniform empty, the code here is amended as follows:

package com.test.mvp.mvpdemo.mvp.v3.basemvp;

import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public abstract class BasePresenter<V extends IBaseView> implements IBasePresenter {
    private SoftReference<IBaseView> mReferenceView;
    private V mProxyView;

    @SuppressWarnings("unchecked")
    @Override
    public void attech(IBaseView view) {
        mReferenceView = new SoftReference<>(view);
        mProxyView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                if (mReferenceView == null || mReferenceView.get() == null) {
                    return null;
                }
                return method.invoke(mReferenceView.get(), objects);
            }
        });
    }

    @SuppressWarnings("unchecked")
    public V getView() {
        return mProxyView;
    }

    @Override
    public void detech() {
        mReferenceView.clear();
        mReferenceView = null;
    }
}

    After using dynamic proxies, we Presenter implementation class do not need to empty type View layer of the judgment, thus saving code, although not much code, but still annoying to write, letting our code becomes more elegant.

    So, this article is over, continue to feed through to BaseMVP this article, we BaseMVP basic framework is also a kind of mold, and to want to do better, but also need to continue to optimize the code. Do not worry, we slowly again and again to get it.

发布了101 篇原创文章 · 获赞 766 · 访问量 87万+

Guess you like

Origin blog.csdn.net/smile_Running/article/details/94984874