Android Mvp架构设计与性能优化

Android Mvp架构设计与性能优化


什么是mvp架构设计?

MVP是模型(Model)、视图(View)、主持人(Presenter)的缩写,分别代表项目中3个不同的模块。

  模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;

  视图(View):负责界面数据的展示,与用户进行交互;

  主持人(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来。

  如下图所示,View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁。其中Presenter中同时持有Viwe层以及Model层的Interface的引用,而View层持有Presenter层Interface的引用。当View层某个界面需要展示某些数据的时候,首先会调用Presenter层的某个接口,然后Presenter层会调用Model层请求数据,当Model层数据加载成功之后会调用Presenter层的回调方法通知Presenter层数据加载完毕,最后Presenter层再调用View层的接口将加载后的数据展示给用户。这就是MVP模式的整个核心过程。


为什么要mvp架构设计?

书面的说法就是为了解耦,为了可维护性,可扩展性。简而言之就是OCP开闭原则,对于扩展开放,对于修改关闭。

但是我更想用个人实战经验来说明架构设计在开发中的好处。初学android的时候觉得android很麻烦,要写很多的配置文件,加上自己也没有多么高深的架构设计能力,所以曾经写一个应用一个service达到了近1000行代码。对,你没听错,后期维护的时候很恶心人,我现在看到那个项目就想吐。这就是没有架构胡乱敲代码所导致的后果。还好google工程师在android里其实内置了很多的设计模式,所以我们的代码才没有更恶心下去。用了mvp架构设计后个人觉得非常的方便,代码风格发生了很大的变化,开始习惯使用泛型,开始习惯不写重复代码,并且开始自己封装一些简单的框架,抽出一些公共的方法。由于上面也讲了mvp具体是怎么回事,我就不多啰嗦了。

AndroidMVP架构实战:

包结构:

renyou.com.mvp.activity

renyou.com.mvp.model

renyou.com.mvp.view

renyou.com.mvp.presenter

renyou.com.mvp.bean

renyou.com.mvp.data

renyou.com.mvp.adapter

renyou.com.mvp.activity
public class MvpActivity extends AppCompatActivity implements MvpView{
    private ListView listview;
    private MvpAdapter mAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvp);
        initView();

        new MvpPresenterV1(this).fetch();
    }


    private void initView() {
        listview= (ListView) findViewById(R.id.lv_main);
    }

    @Override
    public void showLoading() {
        Toast.makeText(getApplicationContext(),"正在加载",Toast.LENGTH_LONG).show();
    }

    @Override
    public void showDatas(List<Renyou> datas) {
        mAdapter=new MvpAdapter(getApplicationContext(), datas);
        listview.setAdapter(mAdapter);
    }
}
renyou.com.mvp.model

MvpModel:model层接口
public interface MvpModel {
    void loadDatas(DataOnLoadingListener listener);

    interface DataOnLoadingListener{
        void onComplete(List<Renyou>datas);
    }
}
MvpModelImplV1:model层实现类
public class MvpModelImplV1 implements MvpModel {
    @Override
    public void loadDatas(DataOnLoadingListener listener) {

        List<Renyou>datas= DataUtil.getInstance().getData();

        listener.onComplete(datas);
    }
}

renyou.com.mvp.view
MvpView:view层接口
public interface MvpView {
    /**
     * 显示加载进度
     */
    void showLoading();

    /**
     * 显示数据
     * @param datas 要显示的数据
     */
    void showDatas(List<Renyou>datas);
}
renyou.com.mvp.presenter
MvpPresenterV1:presenter类
public class MvpPresenterV1 {
    //view
    MvpView mvpView;
    //model
    MvpModel mvpModel=new MvpModelImplV1();

    public MvpPresenterV1(MvpView mvpView){
        this.mvpView=mvpView;
    }

    /**
     * bind view and model
     */
    public void fetch(){
        mvpView.showLoading();
        if(mvpModel!=null){
            mvpModel.loadDatas(new MvpModel.DataOnLoadingListener() {
                @Override
                public void onComplete(List<Renyou> datas) {
                    mvpView.showDatas(datas);
                }
            });
        }
    }
}

renyou.com.mvp.bean

Renyou:bean类

public class Renyou {
    private String name;

    public Renyou(String name){
        this.name=name;
    }

    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }

}

renyou.com.mvp.data

DataUtil:加载数据类
public class DataUtil {
    private static DataUtil dataUtil=null;

    public static DataUtil getInstance(){
        if(dataUtil==null){
            dataUtil=new DataUtil();
        }
        return dataUtil;
    }

    public List<Renyou> getData(){
        List<Renyou> datas = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            Renyou renyou = new Renyou("" + i);
            datas.add(renyou);
        }
        return datas;
    }

}

renyou.com.mvp.adapter

MvpAdapter:listview适配器
public class MvpAdapter extends BaseAdapter {
    private Context context;
    private List<Renyou>datas;
    public MvpAdapter(Context context,List<Renyou>datas){
        this.context=context;
        this.datas=datas;
    }
    @Override
    public int getCount() {
        return datas.size();
    }

    @Override
    public Object getItem(int position) {
        return datas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView==null){
            convertView=View.inflate(context, R.layout.item, null);
        }
        ViewHolder holder=ViewHolder.getHolder(convertView);
        holder.tv.setText(datas.get(position).getName());
        return convertView;
    }

    static class ViewHolder{
        TextView tv;
        public ViewHolder(View convertView){
            tv=(TextView) convertView.findViewById(R.id.id_num);
        }

        public static ViewHolder getHolder(View convertView){
            ViewHolder holder=(ViewHolder) convertView.getTag();
            if(holder==null){
                holder = new ViewHolder(convertView);
                convertView.setTag(holder);
            }
            return holder;
        }
    }

}
我相信有面向对象基础的开发者都可以看的懂上述代码,这里就不一一解释了。

上述mvp代码性能优化

上述代码缺陷:

如图所示:activity/view会持有presenter层的引用,presenter会引用model层的引用。model加载的数据极有可能是网络数据,且极有可能是异步子线程加载的数据。加载这样的数据要耗时,一旦用户点击回退推出了当前的view,则view就被释放了,但是当model层加载数据完成后会回掉监听器,他会拿着view的引用去访问一块已经被释放了的view内存。这样是没有必要的,是浪费资源的,导致了内存的泄漏。

解决方案:

新增的类

MvpBaseActivity基类
public abstract class MvpBaseActivity<V,T extends BasePresenter<V>>extends AppCompatActivity {
    protected T mPresenter;

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

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

    public abstract T createPresenter();
}

BasePresenter基类presenter
public abstract class BasePresenter<T> {
    /**
     * 当内存不足时释放内存
     */
    protected WeakReference<T>mViewRef;

    /**
     * bind presenter with view
     * @param view
     */
    public void attachView(T view){
        mViewRef=new WeakReference<T>(view);
    }

    /**
     * detach view manager
     */
    public void detachView(){
        if(mViewRef!=null){
            mViewRef.clear();
            mViewRef=null;
        }
    }

    protected T getView(){
        return mViewRef.get();
    }
}

修改的类:
MvpPresenterV1让它继承基类presenter
public class MvpPresenterV1 extends BasePresenter<MvpView> {
    //model
    MvpModel mvpModel=new MvpModelImplV1();

    /**
     * bind view and model
     */
    public void fetch(){
        getView().showLoading();
        if(mvpModel!=null){
            mvpModel.loadDatas(new MvpModel.DataOnLoadingListener() {
                @Override
                public void onComplete(List<Renyou> datas) {
                    getView().showDatas(datas);
                }
            });
        }
    }
}

MvpActivity让他继承基类
public class MvpActivity extends MvpBaseActivity<MvpView,MvpPresenterV1> implements MvpView{
    private ListView listview;
    private MvpAdapter mAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvp);
        initView();

        mPresenter.fetch();
    }

    @Override
    public MvpPresenterV1 createPresenter() {
        return new MvpPresenterV1();
    }


    private void initView() {
        listview= (ListView) findViewById(R.id.lv_main);
    }

    @Override
    public void showLoading() {
        Toast.makeText(getApplicationContext(),"正在加载...",Toast.LENGTH_LONG).show();
    }

    @Override
    public void showDatas(List<Renyou> datas) {
        mAdapter=new MvpAdapter(getApplicationContext(), datas);
        listview.setAdapter(mAdapter);
    }
}

这样就完美解决了内存泄漏这个令人烦恼的问题。代码读者多多研究,有点难懂。

























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值