解决mvpz的内存溢出问题

MVP有很多的优点,例如易于维护,易于测试,松耦合,复用性高,健壮稳定,易于扩展等。但是,由于Presenter经常性的需要执行一些耗时操作,那么当我们在操作未完成时候关闭了Activity,会导致Presenter一直持有Activity的对象,造成内存泄漏。 
怎么样解决这个问题呢,我们只要在Activity或者Fragment关闭的时候将Presenter中的引用释放掉就可以了,但是如果有所的界面都去操作那样就变得很麻烦,所以我们在BaseActivity或BaseFragment中去操作,具体代码如下:

public abstract class BasePresenter<T> {

    protected Reference<T> mViewRef;//View接口类型弱引用

    public void attachView(T view) {
        mViewRef = new WeakReference<T>(view); //建立关联
    }

    protected T getView() {
        return mViewRef.get();//获取View
    }

    public boolean isViewAttached() {//判断是否与View建立了关联
        return mViewRef != null && mViewRef.get() != null;
    }

    public void detachView() {//解除关联
        if (mViewRef != null) {
            mViewRef.clear();
            mViewRef = null;
        }
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

这里定义了四个方法,View通过泛型传递进来,Presenter对这个View持有弱引用。

public abstract class BaseActivity<V, T extends BasePresenter<V>> extends LibBaseActivity {

    protected T mPresenter;//Presenter对象

    @SuppressWarnings("unchecked")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPresenter = createPresenter();//创建Presenter
        mPresenter.attachView((V) this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mPresenter.detachView();
    }

    protected abstract T createPresenter();

}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

BaseActivity含有两个泛型参数,第一个是View接口类型,第二个是Presenter的具体类型,在onCreate()中创建通过createPresenter创建一个具体的Presenter,在onDestroy()中释放Presenter中的引用。


--------------------------------------------------------------------------


泛型MVP解决内存泄漏隐患

96 
Whyn 
2016.12.26 21:29*  字数 537  阅读 525 评论 0

背景

我们知道,在MVP模式中,Presenter是同时持有View和Model的引用的,那么,当在Presenter中,假设由于业务需求,需要开辟一条线程进行耗时操作,如果此时View(Activity)退出,由于子线程还在运行,此时,Presenter不能被销毁(子线程是Presenter开辟的内部类,内部类隐式持有外部类的引用),由于Presenter持有view引用,故activity即使退出了,却不能被gc,此时,内存泄露便产生了。
eg:
`

    public class IPresenterImpl implements IPresenter {
    private Contract.IView view;
    private Contract.IModel model;
    public IPresenterImpl(Contract.IView view) {
        this.view = view;
        model = new IModelImpl();
    }

    @Override
    public void loadData() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //模拟耗时操作
                    java.util.concurrent.TimeUnit.SECONDS.sleep(10);
                    ivew.showData();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    ivew.onLoadDataFailed();
                }
            }
        }).start();
    }
}

`
** 注: **当子线程还未运行完时,此时退出activity,则内存泄露。

解决方法

1.定义一个Presenter的基类:BasePresenter,BasePresenter中持有View的弱引用,并在View(Activity)的onCreate中进行attach,在View(Activity)中的onDestroy()中detach。
`

 //V:表示任意view类型,一般是IView
public class BasePresenter<V> {
private WeakReference<V> weakRefView;
public void attach(V view){
        weakRefView = new WeakReference<V>(view);
 }

public void detach() {
    if(isAttach()) {
        weakRefView.clear();
        weakRefView = null;
    }
}
public V obtainView(){
    return isAttach()?weakRefView.get():null;
}

protected boolean isAttach() {
    return weakRefView != null &&
            weakRefView.get() != null;
 }
}

`
** 这里用弱引用主要时防止当Activity被销毁时没走onDestroy **(比如,kill的时候就不走)

2.定义一个Activity基类:BaseActivity,主要就是在这里处理与BasePresenter的引用关系,后续继承这两个类的子类就不用管view与presenter绑定这些事了。

`

public abstract class BaseActivity<V,P extends BasePresenter<V>> 
extends Activity{

protected P mPresenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mPresenter = createPresenter();
    mPresenter.attach((V)this);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    mPresenter.detach();
}

public abstract P createPresenter();

}

`
** createPresenter()作用是让每个Activity都产生自己需要的presenter,由自己决定。**

综上所诉,这样便可以提高MVP的扩展性,以及解决潜在的内存泄露问题。

具体使用方法

通过定义一个通用的基类BasePresenter和一个BaseActivity,解决了Presenter引用View和释放时机问题,Model无需更改,IView层也无需修改,唯一需要更改点写法的就是Presenter。

通常的Presenter接口如下所示:
public interface IPresenter{ void startLoadData(); }
因为所有的Presenter都要继承BasePresenter,而BasePresenter是一个抽象类,所以IPresenter也要更改为抽象类,其他的只需将其接口方法改为抽象方法即可:
public abstract class IPresenter<V> extends BasePresenter<V>{ public abstract void startLoadData(); }
后续的Presenter具体实现类只需继承IPresenter抽象类即可,
public class IPresenterImpl extends IPresenter<IView>{ @Override public void startLoadData(){ //xxxxx } }








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值