Android的MVP模式講解

       UI層越來越複雜,爲了減輕了UI層的責任,也是爲了更好地細分視圖(View)與模型(Model)的功能,讓View專注於處理數 據的可視化以及與用戶的交互,讓Model只關係數據的處理,MVP(Model-View-Presenter)模式應運而生。每個人對MVP模式都有一定的理解,此篇僅供參考交流。

(1)View:負責繪製UI元素、與用戶進行交互(View interface與Presenter進行交互,降低耦合);
(2)Model:依然是業務邏輯和實體模型、操縱數據(有時也實現一個Model interface用來降低耦合);
(3)Presenter:作爲View與Model交互的中間紐帶,負責完成View於Model間的交互(處理與用戶交互的負責邏輯)


項目Demo結構圖:



(1)首先我們需要一個Bean

public class LoginUserBean {
	 private String username;
	 private String password;

	    public String getUsername() {
	        return username;
	    }

	    public void setUsername(String username) {
	        this.username = username;
	    }

	    public String getPassword() {
	        return password;
	    }

	    public void setPassword(String password) {
	        this.password = password;
	    }
}


(2)View的接口,需要用到的方法:

public interface LoginView {
     void clearUsername();
	 
     void clearPassword();
	 
     void setUsernameError();

     void setPasswordError();

     void navigateToHome();
}

(3)LoginActivity實現View接口

public class LoginActivity extends Activity implements LoginView,OnClickListener {

    private ProgressBar progressBar;
    private EditText username;
    private EditText password;
    private Button btn_login;
    private LoginPresenter presenter;

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

    private void initView() {
    	progressBar = (ProgressBar) findViewById(R.id.progress);
        username = (EditText) findViewById(R.id.username);
        password = (EditText) findViewById(R.id.password);
        btn_login=(Button) findViewById(R.id.button);

        btn_login.setOnClickListener(this);
        presenter = new LoginPresenterImpl(this);
		
	}
    @Override
    public void onClick(View v) {
        presenter.validateCredentials(username.getText().toString(), password.getText().toString());
    }
    
    @Override
    public void navigateToHome() {
    	//登錄成功,跳轉主頁
    	//Intent intent=new Intent(this,MainActivity.class);
    	//startActivity(intent);
        Toast.makeText(this,"成功,跳轉",Toast.LENGTH_SHORT).show();
    }
    



	@Override
	public void clearUsername() {
		username.setText("");
		
	}

	@Override
	public void clearPassword() {
		password.setText("");
		
	}


    @Override
    public void setUsernameError() {
        username.setError(getString(R.string.username_error));
    }

    @Override
    public void setPasswordError() {
        password.setError(getString(R.string.password_error));
    }



	@Override
    protected void onDestroy() {
        presenter.onDestroy();
        super.onDestroy();
    }

}

(4)Model接口:

public interface LoginModel {
    void login(String username, String password, OnLoginFinishedListener listener);
}

(5)Model接口的實現類:

public class LoginModelImpl implements LoginModel{

	@Override
    public void login(final String username, final String password, final OnLoginFinishedListener listener) {

        new Handler().postDelayed(new Runnable() {
        	//模擬耗時登錄
            @Override 
            public void run() {
                 //此處判斷用戶密碼
                if (TextUtils.isEmpty(username)){
                    listener.onUsernameError();//model層裏面回調listener
                
                }
                if (TextUtils.isEmpty(password)){
                    listener.onPasswordError();
                 
                }
               //此處成功,(真實應該網絡返回成功,這裏省略)
               //調用回調方法,通過LoginPresenter操作ui層,跳轉到主頁
              listener.onSuccess();
                
            }
        }, 2000);
    }

}

(6)Presenter橋樑接口:

public interface LoginPresenter {
    void validateCredentials(String username, String password);

    void onDestroy();
}
(7)Presenter現實類,實現回調OnLoginFinishedListener,M層通過回調方法操作Ui層:

public class LoginPresenterImpl implements LoginPresenter, OnLoginFinishedListener {
    private LoginView loginView;
    private LoginModel loginModel;

    public LoginPresenterImpl(LoginView loginView) {
        this.loginView = loginView;
        this.loginModel = new LoginModelImpl();
    }
    //ui層調用
    @Override
    public void validateCredentials(String username, String password) {
        loginModel.login(username, password, this);
    }
    @Override
    public void onSuccess() {
        if (loginView != null) {
        	//M層回調後,這裏操作Ui層接口的跳轉
            loginView.navigateToHome();
        }
    }
    @Override
    public void onDestroy() {
        loginView = null;
    }

    @Override
    public void onUsernameError() {
        if (loginView != null) {
            loginView.setUsernameError();
            loginView.clearUsername();
        }
    }

    @Override
    public void onPasswordError() {
        if (loginView != null) {
            loginView.setPasswordError();
            loginView.clearPassword();
        }
    }

	@Override
	public void clearUsername() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void clearPassword() {
		// TODO Auto-generated method stub
		
	}
}

(8)回調接口:

public interface  OnLoginFinishedListener {
	
          void clearUsername();
	 
	  void clearPassword();
	 
	  void onUsernameError();

	  void onPasswordError();

	  void onSuccess();
}

登錄流程解析:

1-首先是點擊了按鈕,在Ui層LoginActivity調用橋樑實現類LoginPresenterImpl的方法validateCredentials()

 @Override
    public void onClick(View v) {
        presenter.validateCredentials(username.getText().toString(), password.getText().toString());
    }

2-LoginPresenterImpl類操作M層

 @Override
    public void validateCredentials(String username, String password) {
        loginModel.login(username, password, this);
    }

3-LoginModelImpl中的login,當後臺數據返回成功時,調用回調方法操作LoginPresenterImpl類onSuccess方法,
這裏onSuccess方法中loginView.navigateToHome()就是操作UI層,達到跳轉主頁.

@Override
    public void login(final String username, final String password, final OnLoginFinishedListener listener) {

        new Handler().postDelayed(new Runnable() {
        	//模擬耗時登錄
            @Override 
            public void run() {
                 //此處判斷用戶密碼
                if (TextUtils.isEmpty(username)){
                    listener.onUsernameError();//model層裏面回調listener
                
                }
                if (TextUtils.isEmpty(password)){
                    listener.onPasswordError();
                 
                }
               //此處成功,(真實應該網絡返回成功,這裏省略)
               //調用回調方法,通過LoginPresenter操作ui層,跳轉到主頁
              listener.onSuccess();
                
            }
        }, 2000);
    }

4-loginView.navigateToHome()方法操作的UI層如下:

@Override
    public void navigateToHome() {
    	//登錄成功,跳轉主頁
    	//Intent intent=new Intent(this,MainActivity.class);
    	//startActivity(intent);
        Toast.makeText(this,"成功,跳轉",Toast.LENGTH_SHORT).show();
    }

 總結:通過上面流程可以看出,View只負責處理與用戶進行交互,並把數據相關的邏輯操作都扔給了Presenter去做。而Presenter調用Model處理完數據之後,再通過IUserView更新View顯示的信息。每個人對MVP模式都有一定的理解,此篇僅供參考交流。



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