Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android資訊 >> Android MVP 實踐

Android MVP 實踐

編輯:Android資訊

本文由碼農網 – 蘇耀東原創,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃!

簡介

本文是參考google官方發布的MVP架構demo以及前人對MVP實現方式的一些總結做的一個簡單demo,在這裡記錄一下一點心得,希望能給想用MVP的人一點幫助。

總體框架

工程目錄結構

首先先看下整個工程的目錄結構:

目錄的代碼組織方式是按照功能來組織的,功能內部分為xactivity、xcontract、xfragment、xpresenter四個類文件(x代表業務名稱)。base文件夾存放一些公用的基類文件,data文件夾存放業務邏輯相關的代碼,utils文件夾則放一些公用的工具類。本demo實現的功能為:通過點擊界面上的按鈕,獲取手機相關信息,獲取過程中加入延時及等待提示(模擬網絡),最終將信息顯示於界面上(簡單演示,只是顯示了系統時間)。

基類

先看下BasePresenter與BaseView這兩個接口類,它們分別是所有Presenter與View的基類。

public interface BasePresenter {
    void start();
}

BasePresenter中含有方法start(),該方法的作用是presenter開始獲取數據並調用view中方法改變界面顯示,其調用時機是在Fragment類的onResume方法中。

public interface BaseView<T> {
    void setPresenter(T presenter);
}

BaseView中含方法setPresenter,該方法作用是將presenter實例傳入view中,其調用時機是在activity的presenter實現類的構造函數中。

契約類

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的接口實現時間的顯示以及提示對話框的顯示及隱藏。

MVP的組織方式

activity的作用

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進行操作展示。

presenter的實現

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層就能夠很好的被劃分。

view的實現

@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方法,處理數據的加載與展示。

簡單歸納

  • activity創建fragment及實例化presenter,在實例化的同時,將fragment作為參數傳遞進去,這樣一來在presenter中就可調用view的接口對界面進行更新、展示
  • presenter實例化時,還調用了view的setPresenter方法,將自身傳遞進去,這樣一來fragment獲得了presenter的實例,便可在view中調用presenter進行業務邏輯的操作
  • view及presenter擁有彼此的實例,實現了在view中調用presenter處理業務,處理完後再presenter中更新view。

model層

簡單介紹下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的地址:本文demo鏈接   官方demo鏈接   個人博客

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved