android MVP 開發模式

android MVP 開發模式的理解

       在進入MVP介紹前。我們先來看一下一直沿用的MVC的開發的模式。


       明人一看上面的結構圖就知道MVC中是允許Model 和 View  進行交互的。

每種模式都有利與弊,不能說那種模式好與不好。爲了“高內聚,低耦合”的思想。個人覺得MVP更能體現之特性。

下面讓我們來看看MVP的結構圖:


   View對應於activity,負責View的繪製以及用戶的交互,理應做到View是最薄的一層,利於UI重新設計與變更。
     Model 數據源與實體模型。比如,保存到本地的數據。數據庫的數據。網絡請求回來的數據。
     Presenter 負責View與Model的交互。起到一箇中間的角色。說白了就是個控制器。由它來控UI的數據來源和UI顯示。

  • 如果理解這三個概念。接下來就說說代碼結構吧。

代碼分塊。這並不是MVP的主旨。可以根據個人愛好來分。最重要的是我們在寫代碼時,如何運用MVP的思維。做到代碼清淅明瞭,維護性高。邏輯簡單明瞭。

接下來看一個簡單的例子。如


/**
 * Created by cc on 16/4/13.
 */
public interface ILoginView {

    String getPhone();

    String getPassWord();

    void setPhone(String phone);

    void setPassWroid(String passWroid);

    void startIndexActivity();

    void startForgetActivity();

    Context getContext();

    void promptToastMessge(String msg);



    void showProgressBar(String msg);

    void setProgressBarMessage(String msg);

    void hideProgressBar();


}

/**
 * Created by cc on 16/4/13.
 */
public interface ILoginMode {

    void onSuccess(Object object);

    void onFail(Object object);
}
/**
 * Created by cc on 16/4/13.
 */
public class LoginService {


    public LoginService(final ILoginMode iLoginMode) {

        //這裏模擬網絡請求。按道理來說。這裏不該出現os包的代碼。這裏只爲了測試。
        // 建設 model層。放在異步線程執行。可以試一下
        //Rx(rxjava或rxandroid) 與 Retrogit
        //Rx(rxjava或rxandroid) 可以簡單理解爲"異步"
        //Retrogit網絡請求

       new Handler().postDelayed(new Runnable() {
           @Override
           public void run() {
               //模擬加載數據

               if (new Random().nextBoolean()){
                   iLoginMode.onSuccess("請求成功");
                   return;
               }
               iLoginMode.onFail("請求失敗");
           }
       },3000);




    }
}

/**
 * Created by cc on 16/4/13.
 */
public class LoginPresenter {

    private ILoginView mILoginView;


    public LoginPresenter(ILoginView iLoginView) {
        mILoginView = iLoginView;
    }

    public void onCreate() {

        LocalLoginPhone localLoginPhone = new LocalLoginPhone();

        String phone = localLoginPhone.getLoginPhone(mILoginView.getContext());

        mILoginView.setPhone(phone);

    }

    public void deletePhoneClick() {

        mILoginView.setPhone("");

    }

    public void deletePassWordClick() {
        mILoginView.setPassWroid("");
    }

    public void forgetPassWordClick() {
        mILoginView.startForgetActivity();
    }

    public void LoginClick() {

        String phone = mILoginView.getPhone();

        if (TextUtils.isEmpty(phone)) {

            mILoginView.promptToastMessge("填寫信息有誤");

            return;
        }

        String possWord = mILoginView.getPassWord();

        if (TextUtils.isEmpty(possWord)) {

            mILoginView.promptToastMessge("填寫信息有誤");

            return;
        }

        mILoginView.showProgressBar("正在加載");

        LoginService loginService = new LoginService(new ILoginMode() {
            @Override
            public void onSuccess(Object object) {
                mILoginView.setProgressBarMessage(object.toString());
                mILoginView.hideProgressBar();

                mILoginView.startIndexActivity();
            }

            @Override
            public void onFail(Object object) {
                mILoginView.setProgressBarMessage(object.toString());
                mILoginView.hideProgressBar();
                mILoginView.promptToastMessge("提交失敗");
            }
        });


    }


}

/**
 * Created by cc on 16/4/13.
 */
public class LogInActivity extends BaseActivity implements ILoginView {


    private EditText login_et_phone, login_et_password;

    private Button login_btn_delete_phone, login_btn_delete_password, login_btn_login, login_btn_forget_password;

    private LoginPresenter mLoginPresenter;

    private LittleDialog mDialog;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.act_login);

        initView();

        mLoginPresenter = new LoginPresenter(this);
        mLoginPresenter.onCreate();
    }



    private void initView() {

        login_et_phone = (EditText) findViewById(R.id.login_et_phone);
        login_et_password = (EditText) findViewById(R.id.login_et_password);
        login_btn_delete_phone = (Button) findViewById(R.id.login_btn_delete_phone);
        login_btn_delete_password = (Button) findViewById(R.id.login_btn_delete_password);
        login_btn_login = (Button) findViewById(R.id.login_btn_login);
        login_btn_forget_password = (Button) findViewById(R.id.login_btn_forget_password);


        login_btn_delete_phone.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mLoginPresenter.deletePhoneClick();
            }
        });
        login_btn_delete_password.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mLoginPresenter.deletePassWordClick();
            }
        });
        login_btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mLoginPresenter.LoginClick();
            }
        });
        login_btn_forget_password.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mLoginPresenter.forgetPassWordClick();
            }
        });

    }

    @Override
    public String getPhone() {
        return login_et_phone.getText().toString().trim();
    }

    @Override
    public String getPassWord() {
        return login_et_password.getText().toString().trim();
    }

    @Override
    public void setPhone(String phone) {

        login_et_phone.setText(phone);

    }

    @Override
    public void setPassWroid(String passWroid) {
        login_et_password.setText(passWroid);
    }

    @Override
    public void startIndexActivity() {
        UIHelper.startActivity(this, IndexActivity.class, null);
    }

    @Override
    public void startForgetActivity() {

    }

    @Override
    public Context getContext() {
        return this;
    }

    @Override
    public void promptToastMessge(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }


    @Override
    public void showProgressBar(String msg) {
        mDialog = new LittleDialog(this, msg);
        mDialog.show();

    }

    @Override
    public void setProgressBarMessage(String msg) {
        if (null != mDialog)
            mDialog.setMessage(msg);
    }

    @Override
    public void hideProgressBar() {

        if (null != mDialog)
            mDialog.dismiss();

    }


}

/**
 * UI操作輔助類
 * @author alafighting 2016-0
 */
public class UIHelper {

    /**
     * 界面跳轉
     * @param context
     * @param activity
     * @param bundle
     */
    public static void startActivity(Context context, Class<? extends Activity> activity, Bundle  bundle) {
        if (context == null) {
            throw new NullPointerException("context不能爲空");
        }
        Intent intent = new Intent(context, activity);

        if (null !=bundle){
            intent.putExtras(bundle);
        }


        context.startActivity(intent);
    }


    /**
     * 打開主界面
     * @param context
     */
    public static void startMain(Context context) {
        startActivity(context, IndexActivity.class,null);
    }

}

/**
 * Created by cc on 16/4/13.
 */
public class BaseActivity extends AppCompatActivity {


    public Context getContext() {
        return super.getApplicationContext();
    }

    public Activity getActivity() {
        return this;
    }

    public <T extends android.support.v4.app.Fragment> T findSupportFragment(Class<T> fragmentClass) {
        android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
        android.support.v4.app.Fragment fragment = fragmentManager.findFragmentByTag(fragmentClass.getName());
        return (T) fragment;
    }

    public <T extends android.support.v4.app.Fragment> T newSupportFragment(Class<T> fragmentClass, Bundle args) {
        android.support.v4.app.Fragment fragment = android.support.v4.app.Fragment.instantiate(getContext(), fragmentClass.getName(), args);
        fragment.setArguments(args);
        return (T) fragment;
    }
}

上面的例子是不是看起來很明瞭。關鍵問題,大家看到這代碼後,會認爲這只是把邏輯代碼模塊的東西放到一另一個類而已。如果你這麼理解。說明你對寫代碼的一個整體認識觀不是很有藝術。人人都說寫代碼是一門藝術。

上面的代碼結構還是有好處的。如,當測試跟你說這接口請求出錯了。出bug了。這時平常我們會去找到這個接口在那個activity裏調用。在那一行代碼裏。聰明的人可能不會這麼幹。或許習慣自已寫測試用例時,只需調用LoginService實現ILoginModel接口就好了,就可以知道自已有沒有搞錯了。是不是很 66666

最後說一個mvp 的優點

MVP的優點:

模型與視圖完全分離,我們可以修改視圖而不影響模型

可以更高效地使用模型,因爲所有的交互都發生在一個地方——Presenter內部

我們可以將一個Presenter用於多個視圖,而不需要改變Presenter的邏輯。這個特性非    常的有用,因爲視圖的變化總是比模型的變化頻繁。

如果我們把邏輯放在Presenter中,那麼我們就可以脫離用戶接口來測試這些邏輯(單    元測試)


說明。上面有一兩張圖是截網上的。如果有侵權,請及時聯繫我刪除,謝謝。

在此感謝以上幾個人。老八,殼,替補,roy,朽木,在我理解MVP 過程中。他們給予我解答



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章