MVP在Android中的初學之路
MVP在Android中的初學之路
最近開始學習Android的架構模式,瞭解到從之前眾所周知的MVC到MVP 甚至現在流行的MVVM等架構。想著以前都是使用MVC來開發,本想直接上MVVM的不過想著一步步來先了解MVP架構,這樣才能更加清楚各種架構的優劣之分。才能再以後工作中結合業務選取合適的架構。開發起來也會更加省事省心。當然架構這種東西也只是相對你的專案來選可能MVP更好 也可能MVVM更好而已。
先介紹下:
MVP的三個模組:Model、View、Presenter
View:負責檢視部分展示、檢視事件處理。Activity、Fragment、Dialog、ViewGroup等 呈現檢視的元件都可以承擔該角色。
Model:負責資料的請求、解析、過濾等資料層操作。
Presenter: View和Model互動的橋樑。
鎮樓圖(Copy):
優點:
1.降低耦合度,隱藏資料,使Activity(或Fragment)中程式碼更加簡潔,只負責處理View的職責;
2.模組職責分工明確;
3.方便單元測試開發;
4.程式碼複用性較高。
案例分析:
UI層的介面:
View
public interface IGrilView {
/**
* UI業務邏輯 載入進度條
*/
void showLoading();
void showGrils(List<Girl> grils);
}
Mode:
/** * 模型層 */ public class GirlModeImlV implements IGirlMode { @Override public void loaddata(GirlOnLoadlitener girlOnLoadlitener) { final 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, "四顆星", "夏裝新款下襬波浪邊掛脖露肩")); data.add(new Girl(R.drawable.f8, "五顆星", "夏天新款歐美時尚潮流休閒百")); data.add(new Girl(R.drawable.f9, "四顆星", "迷依詩諾夏季新款小香風甜美性感夜")); data.add(new Girl(R.drawable.f10, "三顆星", "安巴克夏季新款韓版時尚套裝性感")); girlOnLoadlitener.complete(data); } }
/**
* 監聽資料返回
*/
public interface IGirlMode {
void loaddata(GirlOnLoadlitener girlOnLoadlitener);
interface GirlOnLoadlitener {
void complete(List<Girl> list);
}
}
MainActivity:
public class MainActivity extends AppCompatActivity implements IGrilView {
ListView listView;
GirlPresenter girlPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listview);
//例項化P層 並抓取資料
girlPresenter = new GirlPresenter(this);
girlPresenter.fectch();
}
@Override
public void showLoading() {
Toast.makeText(this, "正在載入中...", Toast.LENGTH_SHORT).show();
}
@Override
public void showGrils(List<Girl> grils) {
listView.setAdapter(new GirlListAdapter(this, grils));
}
}
主要的P層:
public class GirlPresenter {
//持有UI層的引用
IGrilView iGrilView;
//資料層的引用
IGirlMode iGirlMode = new GirlModeImlV();
public GirlPresenter(IGrilView iGrilView) {
this.iGrilView = iGrilView;
}
public void fectch() {
iGrilView.showLoading();
if (iGirlMode != null) {
iGirlMode.loaddata(new IGirlMode.GirlOnLoadlitener() {
@Override
public void complete(List<Girl> list) {
//回撥檢視層
iGrilView.showGrils(list);
}
});
}
}
}
這種應該是比較簡單的MVP架構方式了。不過這種存在的問題也不少
1.持有Activity的引用 在網路載入時退出 會造成OOM.
2.P層和V層太複雜 可以進行封裝成BasePresenter BaseActivity
下面是改造的:
BasePresenter:採用泛型在Activity的onCreate執行繫結一個弱引用 在onDestory方法進行分離達到解除引用置空 讓GC回收掉。
/**
* @param <T> 對應每個Activity的UI Presnter
*/
public abstract class BasePresenter<T> {
/**
* 持有UI介面的弱引用
*/
protected WeakReference<T> mWeakReference;
/**
* 繫結UI物件引用
*/
public void attachView(T view) {
mWeakReference = new WeakReference<T>(view);
}
/**
* 載入資料
*/
public abstract void fectch();
/**
* 解綁UI的引用物件
*/
public void dettach() {
if (mWeakReference != null) {
mWeakReference.clear();
mWeakReference = null;
}
}
}
BaseActivity: 這裡也採用泛型和採用模板法 讓具體的子類去實現Presenter
public abstract class BaseAcivity<V, T extends BasePresenter<V>> extends AppCompatActivity {
protected T mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter = createPresenter();
mPresenter.attachView((V) this);
}
protected abstract T createPresenter();
@Override
protected void onDestroy() {
mPresenter.dettach();
super.onDestroy();
}
}
具體的實現MvpMainActivity
public class MvpMainActivity extends BaseAcivity<IGrilView, MvpGirlPresenter<IGrilView>> implements IGrilView {
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listview);
mPresenter.fectch();
}
@Override
protected MvpGirlPresenter<IGrilView> createPresenter() {
return new MvpGirlPresenter<>(this);
}
@Override
public void showLoading() {
Toast.makeText(this, "正在載入中...", Toast.LENGTH_SHORT).show();
}
@Override
public void showGrils(List<Girl> grils) {
listView.setAdapter(new GirlListAdapter(this, grils));
}
}
因為這是一個比較簡單的MVP,沒有結合RxJava Retrofit Okhttp3等框架 不過後面會嘗試寫這一部分。以上如有寫得不對的請指正。感謝各位的閱讀。
本Demo的地址:https://github.com/eternityzqf/MvpDemo