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);
}
}