MVP模式的簡單理解

這幾天一直加班,好不容易到了週末,就狂睡一通,結果白天睡覺,晚上反而睡不着了。閒着也麼事,就起來寫寫博客吧,記錄一下最近工作中遇到的問題。

剛進新公司的時候,接手了公司的項目,可是剛拿到代碼就蒙了,完全看不懂。。。新公司用的是MVP架構,但是我之前的公司用的是MVC架構,有的人可能就會問了,爲了麼MVP架構這麼流行,還有公司不去用它,這個我也沒辦法,也不是我們今天討論的話題。

拿着公司的代碼,邊做功能邊學習MVP,這個還是比較痛苦的,剛開始什麼都看不懂,方法在哪裏被調用的也看不出來,只能慢慢摸索,好在這兩天的努力沒白費,終於把MVP弄懂了,下面我就以我的思路來解釋一下什麼叫MVP。

我們就寫一個簡單的Demo吧,從實例中來學習比較快。網上大部分的MVP例子都是登錄註冊,我也來寫一個登錄註冊。

首先,我們需要定義一個資源文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical">  

    <EditText  
        android:id="@+id/username_et"  
        android:hint="請輸入賬號"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content" />  

    <EditText  
        android:id="@+id/password_et"  
        android:hint="請輸入密碼"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:inputType="textPassword" />  

    <Button  
        android:id="@+id/login_btn"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="登錄"/>  

</LinearLayout>

代碼很簡單,一個賬號輸入框,一個密碼輸入框,一個登錄按鈕

然後看一下,不使用MVP模式的MainActivity代碼:

public class MainActivity extends Activity implements OnClickListener {  

    private static final String TAG = "MainActivity";  
    public static final String USERNAME="wuzhanglao";  
    public static final String PASSWORD="470782682";  

    private EditText username_et;  
    private EditText password_et;  
    private Button login_btn;  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        initView();  
    }  

    private void initView() {  
        username_et = (EditText) findViewById(R.id.username_et);  
        password_et = (EditText) findViewById(R.id.password_et);  
        login_btn = (Button) findViewById(R.id.login_btn);  
        login_btn.setOnClickListener(this);  
    }  

    @Override  
    public void onClick(View v) {  
        switch (v.getId()) {  
        case R.id.login_btn:  
            String username = username_et.getText().toString();  
            String password = password_et.getText().toString();  
            if(username.isEmpty() || password.isEmpty()){  
                Log.d(TAG, "賬號或者密碼不能爲空");  
            } else if(username.length() <8 || password.length()<9){  
                Log.d(TAG, "賬號至少8位,密碼至少10位");  
            } else if(username.equals(USERNAME)){  
                if(password.endsWith(PASSWORD)){  
                    Log.d(TAG, "恭喜你,登錄成功");  
                } else {  
                    Log.d(TAG, "登錄失敗->密碼錯誤");  
                }  
            }  
            break;  
        }  
    }  
}

前面的都不用看,直接看onClick()方法裏面,大家有沒有看到,case R.id.login_btn後面的代碼有點多,有的人就問啦,不是很多啦,也就十幾行。對,也就十幾行,但是正式的公司項目中是不可能只有一個點擊事件的,也就是switch語句裏面會有很多case語句,到時候修改代碼的時候可以把你煩死,一個switch塊就有幾百行幾千行代碼,會瘋掉的~~~


發火

反正我看到這種代碼就沒好心情了

下面我們稍微改進一下,讓代碼簡潔一些,請看我是如何修改的:

@Override  
public void onClick(View v) {  
    switch (v.getId()) {  
    case R.id.login_btn:  
        //把登錄事件封裝成了一個方法,直接調用就行了,代碼看起來簡潔而且容易理解  
        LoginEvent();  
    break;  
    }  
}  

private void LoginEvent() {  
    String username = username_et.getText().toString();  
    String password = password_et.getText().toString();  
    if (username.isEmpty() || password.isEmpty()) {  
        Log.d(TAG, "賬號或者密碼不能爲空");  
    } else if (username.length() < 8 || password.length() < 9) {  
        Log.d(TAG, "賬號至少8位,密碼至少10位");  
    } else if (username.equals(USERNAME)) {  
        if (password.endsWith(PASSWORD)) {  
            Log.d(TAG, "恭喜你,登錄成功");  
        } else {  
            Log.d(TAG, "登錄失敗->密碼錯誤");  
        }  
    }  
}

其他代碼都沒有變,我只是把登錄事件封裝到一個方法體裏面了,這樣封裝一下,會很好理解,代碼也就簡潔了些。但是現在還有一個問題,如果點擊事件很多,你必須要給每個點擊事件封裝一個方法,誇張點說,如果有100個點擊事件,那我豈不是要在MainActivity裏面封裝100個方法嗎?其實挺心疼MainActivity的,一個大姑娘家的,既要處理View層,又要處理業務邏輯層,把管家的事情都做了,能不憔悴嗎,能有人喜歡嗎

於是MVP架構就出現了,就是爲了解決MainActivity大妹子的煩惱,首先我們需要定義一個接口,接口乾嘛用的???(握了棵草,也不講講清楚,上來就接口!!!)沒關係,我在代碼中給你註釋了,不怕你看不懂

public interface IMainView {  
    //如果登錄成功,管家會撥打這個電話(接口)  
    void LoginSuccess();  
    //如果登錄失敗,管家會撥打這個電話(接口),並告訴MainActivity大妹子爲什麼登錄失敗  
    void LoginFailed(String msg);  
}

然後我們讓MainActivity實現這個接口

public class MainActivity extends Activity implements OnClickListener, IMainView {  

    private static final String TAG = "MainActivity";  
    public static final String USERNAME = "wuzhanglao";  
    public static final String PASSWORD = "470782682";  

    private EditText username_et;  
    private EditText password_et;  
    private Button login_btn;  
    private MainPresenter mainPresenter;  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        initView();  
    }  

    private void initView() {  
        username_et = (EditText) findViewById(R.id.username_et);  
        password_et = (EditText) findViewById(R.id.password_et);  
        login_btn = (Button) findViewById(R.id.login_btn);  
        login_btn.setOnClickListener(this);  

        //僱一個叫main的管家,然後把自己登錄成功和登錄失敗的聯繫方式給他  
        //如果登錄成功,管家會撥打loginSuccess這個電話  
        //如果登錄失敗,管家會撥打logniFailed(String msg)這個電話  
        mainPresenter = new MainPresenter(this);  
    }  

    @Override  
    public void onClick(View v) {  
        switch (v.getId()) {  
        case R.id.login_btn:  
            String username = username_et.getText().toString();  
            String password = password_et.getText().toString();  
            // 讓自己的管家去處理登錄事件  
            mainPresenter.login(username, password);  
            break;  
        }  
    }  

    @Override  
    public void LoginSuccess() {  
        Log.d(TAG, "管家打電話過來說:登錄成功");  
    }  

    @Override  
    public void LoginFailed(String msg) {  
        Log.e(TAG, "管家打電話過來說:登錄失敗,失敗原因:" + msg);  
    }  
}

看到沒有,我們的大妹子在onclick點擊事件裏面讓自己的管家來處理登錄事件,而自己只需要關心有沒有登錄成功,這樣就顯得輕鬆許多

我們看看大管家是怎麼來做事情的

//MainActivity的管家  
public class MainPresenter {  

    private static final String TAG = "MainPresenter";  

    private IMainView view;  

    public MainPresenter(IMainView view) {  
        this.view = view;  
    }  

    // Main管家處理登錄邏輯  
    public void login(String username, String password) {  
        if (username.isEmpty() || password.isEmpty()) {  
            view.LoginFailed("賬號或密碼不能爲空");  
        } else if (username.length() < 8 || password.length() < 9) {  
            view.LoginFailed("賬號至少8位,密碼至少9位");  
        } else if (username.equals(MainActivity.USERNAME)) {  
            if (password.endsWith(MainActivity.PASSWORD)) {  
                // 登錄成功,main撥打loginSuccess()電話通知主人登錄成功了  
                view.LoginSuccess();  
            } else {  
                // 登錄失敗,main撥打loginFailed()電話通知主人登錄失敗了,並告知失敗原因  
                view.LoginFailed("密碼錯誤");  
            }  
        }  
    }  
}

大管家會處理登錄事件,然後把處理結果告訴大妹子,讓大妹子根據不同的結果來進行不同的操作



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