Android MVP模式實(shí)踐總結(jié)(附帶簡單例子)

Android MVP模式實(shí)踐總結(jié)(附帶簡單例子)

最近在做畢業(yè)設(shè)計(jì),題目不是很難,但是后來發(fā)現(xiàn)功能有點(diǎn)多,感覺是苦力活,還好用的是設(shè)計(jì)MVP模式,雖然剛開始也不是特別理解,不過寫的東西多就會(huì)發(fā)現(xiàn)這個(gè)模式的好處。

  1. 代碼雖然好像多了,但思路非常清晰,敲代碼的速度特別快,特別酸爽。
  2. 出現(xiàn)Bug很容易知道哪里出差錯(cuò)。

粽子,感覺開發(fā)效率快了,然后錯(cuò)誤少了。

感覺,學(xué)MVP最好還是看下官方的介紹,如果英文過得去的話。

https://github.com/googlesamples/android-architecture/tree/todo-mvp/

首先, 為什么不用傳統(tǒng)的MVC(model, view, controller)呢,因?yàn)閭鹘y(tǒng)的MVC模式在Android中,把View和controller都雜糅到Activity當(dāng)中,導(dǎo)致Activity越來越臃腫,使得難以開發(fā)和維護(hù)。而MVP(model, view, presenter)模式中,則把一些業(yè)務(wù)邏輯分離出來放到Presenter中,在MVP中的M(model)和V(view)是沒有箭頭連接的,也就是MVP中(View只需要做些與用戶相關(guān)的操作,即繪制界面以及與用戶交互),其他的業(yè)務(wù)功能邏輯都交由Presenter來完成。

在官方介紹中有Contract這個(gè)Interface,里面定義了View和Presenter接口,其實(shí)Contract在mvp中什么角色也不是,只是把view和presenter定義在一起方便管理。

現(xiàn)在給個(gè)簡單例子:

  1. 假設(shè)我們要從網(wǎng)絡(luò)獲取數(shù)據(jù)并顯示用戶的個(gè)人界面;
  2. 同時(shí)我們可以更改用戶數(shù)據(jù)并上傳到服務(wù)器;
  3. 為了簡單起見并不真正的獲取網(wǎng)絡(luò)數(shù)據(jù),也省去了異步等操作,在實(shí)際開發(fā)中都是要考慮的。

首先來看View和Presenter的接口定義

public interface BasePresenter {
    void start();
}

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

public interface UserInfoContract {

    interface Presenter extends BasePresenter{
        void loadUserInfo(); 
        void changeAge();
    }
    interface View extends BaseView<Presenter>{
        void showUserInfoView(UserInfo userInfo);
        void showErrorMessage(String errMsg);
        UserInfo getUserInfo();

    }
}

可以看到在BaseView這個(gè)基類接口中含有setPresenter,從圖上也可以看出,View和Presenter是可以相互交換數(shù)據(jù)的,所以一般都會(huì)互相持有對方的引用。我們再看看它們的實(shí)現(xiàn)類。

public class UserInfoActivity extends AppCompatActivity implements UserInfoContract.View{

    TextView nameTxt;
    TextView ageTxt;
    EditText newAgeEdit;
    Button change;
    UserInfoContract.Presenter presenter;
    UserInfo info;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_info);
        nameTxt = (TextView)findViewById(R.id.name);
        ageTxt = (TextView)findViewById(R.id.age);
        newAgeEdit = (EditText)findViewById(R.id.new_age);
        change = (Button)findViewById(R.id.change);
        change.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String str = newAgeEdit.getText().toString();
                if(str.length() !=0 ){
                    int ageInt = Integer.valueOf(str);
                    info.setAge(ageInt);
                    presenter.changeAge();
                }
            }
        });
        //創(chuàng)建Presenter
        UserInfoContract.Presenter presenter =new UserInfoPresenter(this);
    }

    @Override
    public void showUserInfoView(UserInfo userInfo) {
        //更新用戶界面
        info = userInfo;
        nameTxt.setText(userInfo.getName());
        ageTxt.setText(userInfo.getAge() + "");
    }

    @Override
    public void showErrorMessage(String errMsg) {
        //顯示錯(cuò)誤信息
        Toast.makeText(this,errMsg,Toast.LENGTH_LONG).show();
    }

    @Override
    public UserInfo getUserInfo() {
        return info;
    }

    @Override
    public void setPresenter(UserInfoContract.Presenter presenter) {
        this.presenter = presenter;
    }



}

public class UserInfoPresenter implements UserInfoContract.Presenter {
    UserInfoContract.View view;
    UserInfo info;

    public UserInfo getNetworkData(){
        //模擬網(wǎng)絡(luò)io等操作,獲取數(shù)據(jù)
        if(info == null){
            info = new UserInfo();
            info.setAge(16);
            info.setId(1);
            info.setName("lawliex");
        }
        return info;
    }

    public UserInfoPresenter(UserInfoContract.View view) {
        this.view = view;
        view.setPresenter(this);
        start();
    }



    @Override
    public void loadUserInfo() {

        UserInfo userInfo = getNetworkData();

        //取得數(shù)據(jù)后,因?yàn)閜resenter持有view的引用,可以回調(diào)view的相關(guān)方法,此處假設(shè)加載數(shù)據(jù)成功,回調(diào)顯示正常界面
        view.showUserInfoView(userInfo);
        //如果發(fā)生錯(cuò)誤則回調(diào)
        //view.showErrorMessage("error");
    }

    @Override
    public void changeAge() {
        info = view.getUserInfo();
        //模擬更新數(shù)據(jù)到服務(wù)器,成功后,更新View的數(shù)據(jù)
        start();
    }

    @Override
    public void start() {
        loadUserInfo();
    }
}

項(xiàng)目源碼

https://github.com/PoleLive/mvp

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容