本文是參考google官方發佈的MVP架構demo以及前人對MVP實現方式的一些總結作的一個簡單demo,在這裏記錄一下一點心得,但願能給想用MVP的人一點幫助。 html
首先先看下整個工程的目錄結構: 目錄的代碼組織方式是按照功能來組織的,功能內部分爲xactivity、xcontract、xfragment、xpresenter四個類文件(x表明業務名稱)。base文件夾存放一些公用的基類文件,data文件夾存放業務邏輯相關的代碼,utils文件夾則放一些公用的工具類。本demo實現的功能爲:經過點擊界面上的按鈕,獲取手機相關信息,獲取過程當中加入延時及等待提示(模擬網絡),最終將信息顯示於界面上(簡單演示,只是顯示了系統時間)。java
先看下BasePresenter與BaseView這兩個接口類,它們分別是全部Presenter與View的基類。android
public interface BasePresenter {
void start();
}複製代碼
BasePresenter中含有方法start(),該方法的做用是presenter開始獲取數據並調用view中方法改變界面顯示,其調用時機是在Fragment類的onResume方法中。git
public interface BaseView<T> {
void setPresenter(T presenter);
}複製代碼
BaseView中含方法setPresenter,該方法做用是將presenter實例傳入view中,其調用時機是在activity的presenter實現類的構造函數中。github
public interface GetPhoneInfoContract {
interface View extends BaseView<Presenter> {
void setTime(String time);
void showLoading();
void hideLoading();
}
interface Presenter extends BasePresenter {
void getTime();
}
}複製代碼
與比較常見的mvp實現不一樣,官方的實現中加入了契約類來統一管理view與presenter的全部的接口,這種方式使得view與presenter中有哪些功能,一目瞭然,維護起來也方便,該實例中presenter的接口實現獲取系統時間,view的接口實現時間的顯示以及提示對話框的顯示及隱藏。網絡
activity做爲全局的控制者,負責建立view以及presenter實例,並將兩者聯繫起來,具體的view交由fragment來實現,二者各司其職。架構
@EActivity(R.layout.get_phone_info_act)
public class GetPhoneInfoActivity extends ActionBarActivity {
private FragmentManager fm;
private GetPhoneInfoFragment mGetPhoneInfoFragment = new GetPhoneInfoFragment_();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setDefaultFragment();
new GetPhoneInfoPresenter(mGetPhoneInfoFragment);
}
private void setDefaultFragment() {
fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.add(R.id.fragcontent, mGetPhoneInfoFragment);
transaction.commit();
}
}複製代碼
本例中,activity中經過setDefaultFragment()設置了fragment,以後實例化GetPhoneInfoPresenter,並將frament傳遞進去,實如今presenter中經過fragment的接口對view進行操做展現。框架
public class GetPhoneInfoPresenter implements GetPhoneInfoContract.Presenter{
private final GetPhoneInfoContract.View mGetPhoneInfoView;
private PhoneInfoBiz phoneInfoBiz;
public GetPhoneInfoPresenter(GetPhoneInfoContract.View getPhoneInfoView) {
mGetPhoneInfoView = getPhoneInfoView;
mGetPhoneInfoView.setPresenter(this);
phoneInfoBiz = new PhoneInfoBizIml();
}
@Override
public void start() {
getTime();
}
@Override
public void getTime() {
mGetPhoneInfoView.showLoading();
phoneInfoBiz.getPhoneInfo(new PhoneInfoBiz.GetPhoneInfoCallback() {
@Override
public void onGetPhoneInfo(PhoneInfo phoneInfo) {
mGetPhoneInfoView.setTime(phoneInfo.getTime());
mGetPhoneInfoView.hideLoading();
}
});
}
}複製代碼
presenter構造函數中調用了view的setPresenter方法將自身實例傳入,start方法中處理了數據加載與展現。若是須要界面作對應的變化,直接調用view層的方法便可,這樣view層與presenter層就可以很好的被劃分。ide
@EFragment(R.layout.get_phone_info_frag)
public class GetPhoneInfoFragment extends Fragment implements GetPhoneInfoContract.View {
private GetPhoneInfoContract.Presenter mPresenter;
ProgressDialog dialog;
@ViewById
TextView tv_time;
@ViewById
Button btn_get_time;
@Click
void btn_get_time() {
mPresenter.getTime();
}
@AfterViews
void initView() {
dialog = new ProgressDialog(getActivity());
}
@Override
public void onResume() {
super.onResume();
mPresenter.start();
}
@Override
public void setPresenter(GetPhoneInfoContract.Presenter presenter) {
if (presenter != null)
mPresenter = presenter;
}
@Override
@UiThread
public void setTime(String time) {
tv_time.setText(time);
}
@Override
public void showLoading() {
dialog.setTitle("請稍候");
dialog.setMessage("loading!");
dialog.show();
}
@Override
public void hideLoading() {
dialog.dismiss();
}
}複製代碼
setPresenter方法繼承於父類,經過該方法,view得到了presenter得實例,從而能夠調用presenter代碼來處理業務邏輯。在onResume中還調用了presenter得start方法,處理數據的加載與展現。函數
簡單介紹下model層,PhoneInfo對象存儲手機相關信息,PhoneInfoBiz爲藉口類實現該業務所須要的接口及回調接口,PhoneInfoBizIml爲接口的實現類。直接貼代碼:
public interface PhoneInfoBiz {
interface GetPhoneInfoCallback {
void onGetPhoneInfo(PhoneInfo phoneInfo);
}
void getPhoneInfo(GetPhoneInfoCallback getPhoneInfoCallback);
}複製代碼
public class PhoneInfoBizIml implements PhoneInfoBiz{
@Override
public void getPhoneInfo(final GetPhoneInfoCallback getPhoneInfoCallback) {
new Thread(new Runnable() {
@Override
public void run() {
try {
PhoneInfo phoneInfo = new PhoneInfo();
phoneInfo.setTime(System.currentTimeMillis() + "");
phoneInfo.setMobileType(Build.MODEL);
phoneInfo.setMobileVer(Build.VERSION.RELEASE);
Thread.sleep(1000);
getPhoneInfoCallback.onGetPhoneInfo(phoneInfo);
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
}
}複製代碼
至此,一個簡單的mvp框架到此結束,對於mvp的使用目前也還在探索中,上例是結合官方發佈的demo作的一個簡化工程,有不足之處歡迎一塊兒探討交流!
最後附上本文demo及官方demo的地址:
本文首發地址連接:www.codeceo.com/article/and…