Android 项目结构MVC & MVP 二 源码

本文参考:腾讯课堂-MVP核心揭秘-企业级架构搭建与性能优化

源码 github:https://github.com/01wneo/MVP

这个版本的源码减少了一部分注释:点击下载 MVP04nologver

如果运行不了,新建工程拷贝源代码。

1. 图片资源

2. 源码

BaseActivity.java

/**
 * V 子泛型:View 要使用的;
 * T 表示层要使用的;
 */
public abstract class BaseActivity<V, T extends BasePresenter<V>> extends Activity {
    // 表示层的引用
    public T girlPresenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        girlPresenter = createPresenter();// 调用表示层的选择
        girlPresenter.attachView((V) this); // 传入当前的 activity
    }

    // 表示层的选择:写一个抽象的方法,让继承baseactivity的类必须选择一个抽象层
    protected abstract T createPresenter();

    @Override
    protected void onDestroy() {// activity 异常退出加到activity声明周期中进行处理
        super.onDestroy();
        girlPresenter.detachView();
    }
}

MainActivity.java


/**
 * ① 根除 activity 内存泄漏的问题;
 * ② 让 mvp 更方便使用;
 * 实例:
 * 1.解决activity和presenter过多,每个activity都进行绑定解绑,反复操作的问题;
 * 2.由activity选择表示层,而不是在接口中new;
 * 3.有很多个表示层的时候,多个View可以选择同一个Presenter,
 * 但是View和Model一定会有很多个;
 */
public class MainActivity extends BaseActivity<IGirlView, GirlPresenter<IGirlView>> implements IGirlView {
    private GridView listView;
//    GirlPresenter girlPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = findViewById(R.id.listview);
//        girlPresenter = new GirlPresenter();
        // 进行绑定,解决内存泄漏,不再是内存紧张的时候,只要是GC有空就会回收
//        girlPresenter.attachView(this); 在 baseactivity中已经做了
        girlPresenter.fetch();
    }

    @Override
    protected GirlPresenter<IGirlView> createPresenter() {
        return new GirlPresenter<>();
    }

//    @Override
//    protected void onDestroy() { 在 baseactivity中已经做了
//        super.onDestroy();
//        girlPresenter.detachView();    // 进行绑定,解决内存泄漏,不再是内存紧张的时候,只要是GC有空就会回收
//    }

    @Override
    public void showLoading() {
        Toast.makeText(this, "加载成功", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showGirls(List<Girl> girls) {
        GirlAdapter adapter = new GirlAdapter(this, girls);
        listView.setAdapter(adapter);
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <GridView
        android:id="@+id/listview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="200dp"
        android:layout_height="200dp" />


    <TextView
        android:id="@+id/tv_like"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tv_style"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

Girl.java

public class Girl {
    public int icon;
    public String like;
    public String style;

    public Girl(int icon, String like, String style) {
        this.icon = icon;
        this.like = like;
        this.style = style;
    }
}

GirlAdapter.java

public class GirlAdapter extends BaseAdapter {
    private List<Girl> girls;
    private LayoutInflater inflater;

    public GirlAdapter(Context context, List<Girl> girs) {
        inflater = LayoutInflater.from(context);
        this.girls = girs;
    }


    @Override
    public int getCount() {
        return girls.size();
    }

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = inflater.inflate(R.layout.item, null);
        Girl g = girls.get(position);
        ImageView iv_icon = view.findViewById(R.id.iv_icon);
        iv_icon.setImageResource(g.icon);

        TextView tv_like = view.findViewById(R.id.tv_like);
        tv_like.setText("喜欢程度:"+g.like);

        TextView tv_style = view.findViewById(R.id.tv_style);
        tv_style.setText(g.style);
        return view;
    }
}

IGirlView.java

/**
 * 定义出所有的 UI 逻辑
 */
public interface IGirlView {
    // 加载进度
    void showLoading();

    /*
    * List showGirls(); 这个是使用方法的返回值的方式,
    * 使用这个方式获取网络中的数据,可能会使UI卡主
    */
    /*显示 ListView 中的数据(使用回调的方式返回数据)
    * 通过参数把参数的结果带回到activity
    * */
    void showGirls(List<Girl> girls);
}

BasePresenter.java

/**
 * 向上抽一个基类
 */

public class BasePresenter<T> {
    // 1.view 层的引用
//    IGirlView girlView;// 不可以使用new的方式
    // 解决内存泄漏,使用弱引用,GC 在系统内存紧张的时候回收
    protected WeakReference<T> mViewRef;

    // 进行绑定,解决内存泄漏,不再是内存紧张的时候,只要是GC有空就会回收
    public void attachView(T view) {
        mViewRef = new WeakReference<>(view);
    }

    // 进行绑定,解决内存泄漏,不再是内存紧张的时候,只要是GC有空就会回收
    public void detachView() {
        mViewRef.clear();
    }
}

GirlPresenter.java

/**
 * 表示层
 */
public class GirlPresenter<T extends IGirlView> extends BasePresenter<T> {// 使用泛型,更加灵活
    // 2.model 层的引用
    IGirlModel girlModel = new GirlModelImpl();// 可以使用new的方式

    // 3.构造方法
    /*public GirlPresenter(IGirlView girlView, IGirlModel girlModel) {
        // view 是视图的一个activity,activity 不能用new Activity
        this.girlView = girlView;
        this.girlModel = girlModel;
    }*/
//    public GirlPresenter(T view) {// 使用泛型,更加灵活
    public GirlPresenter() {// 使用绑定的方法
//        this.girlView = view;
//        mViewRef = new WeakReference<>(view);// 软引用,解决内存泄漏
    }

    // 4.执行操作(UI逻辑)
    public void fetch() { // 提取
        if (/*girlView*/ mViewRef.get() != null) {
            /*girlView*/
            mViewRef.get().showLoading();
            if (girlModel != null) {
                girlModel.loadGirl(new IGirlModel.GirlOnLoadListener() {
                    @Override
                    public void onComplete(List<Girl> girls) {
                        if (/*girlView*/ mViewRef.get() != null) {
                            /*girlView*/
                            mViewRef.get().showGirls(girls);
                        }
                    }
                });
            }
        }
    }
}

GirlModelImpl.java

public class GirlModelImpl implements IGirlModel {

    @Override // 传递数据
    public void loadGirl(GirlOnLoadListener girlOnLoadListener) {
        List<Girl> data = new ArrayList<Girl>();
        data.add(new Girl(R.drawable.f1, "五颗星", "时时尚潮流时尚潮流时尚潮流尚潮流"));
        data.add(new Girl(R.drawable.f2, "二颗星", "米意米意识诺米意识诺米意识诺识诺"));
        data.add(new Girl(R.drawable.f3, "五颗星", "春春夏秋冬春夏秋冬春夏秋冬夏秋冬"));
        data.add(new Girl(R.drawable.f4, "一颗星", "锌矿雕刻机房啥来得快"));
        data.add(new Girl(R.drawable.f5, "五颗星", "阿萨德大所大所大所大所多"));
        data.add(new Girl(R.drawable.f6, "三颗星", "请问请问请问请问恶趣味请问"));
        data.add(new Girl(R.drawable.f7, "五颗星", "五洲新春V字形从V字形从"));
        data.add(new Girl(R.drawable.f8, "一颗星", "V过好几个号个换个换个个换个"));
        data.add(new Girl(R.drawable.f9, "五颗星", "华为认为人生巅峰手电筒赵大夫VC"));
        data.add(new Girl(R.drawable.f10, "四颗星", "玩儿玩儿飞山东人玩儿为睡房顶玩儿"));

        girlOnLoadListener.onComplete(data); // 传递数据,回调到上一层
    }
}

IGirlModel.java

/**
 * 用来加载数据
 */
public interface IGirlModel {
    /*
     * void loadGirl(List data);
     * 当数据来源是网络,服务,
     * 如果超时,界面就会卡主
     * */

    void loadGirl(GirlOnLoadListener girlOnLoadListener);// 将数据回调回去

    // 设计一个内部的回调接口
    interface GirlOnLoadListener {
        void onComplete(List<Girl> girls);
    }
}

 

发表评论

zh_CNChinese
zh_CNChinese