android中MVP模式(一) - 清风明月的专栏 - CSDN博客
presenter 主持人。主导器
======
1. 明确需求,界面如下:可存,可根据id读取数据。
- public class UserBean {
- private String mFirstName;
- private String mLastName;
- public UserBean(String firstName, String lastName) {
- this. mFirstName = firstName;
- this. mLastName = lastName;
- }
- public String getFirstName() {
- return mFirstName;
- }
- public String getLastName() {
- return mLastName;
- }
- }
- public interface IUserModel {
- void setID(int id);
- void setFirstName(String firstName);
- void setLastName(String lastName);
- int getID();
- UserBean load(int id);// 通过id读取user信息,返回一个UserBean
- }
- public interface IUserView {
- int getID();
- String getFristName();
- String getLastName();
- void setFirstName(String firstName);
- void setLastName(String lastName);
- }
- public class UserPresenter {
- private IUserView mUserView;
- private IUserModel mUserModel;
- public UserPresenter(IUserView view) {
- mUserView = view;
- mUserModel = new UserModel();
- }
- public void saveUser( int id, String firstName, String lastName) {
- mUserModel.setID(id);
- mUserModel.setFirstName(firstName);
- mUserModel.setLastName(lastName);
- }
- public void loadUser( int id) {
- UserBean user = mUserModel.load(id);
- mUserView.setFirstName(user.getFirstName()); // 通过调用IUserView的方法来更新显示
- mUserView.setLastName(user.getLastName());
- }
- }
- public class MainActivity extends Activity implements OnClickListener,IUserView {
- UserPresenter presenter;
- EditText id,first,last;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout. activity_main);
- findViewById(R.id. save).setOnClickListener( this);
- findViewById(R.id. load).setOnClickListener( this);
- id = (EditText) findViewById(R.id. id);
- first = (EditText) findViewById(R.id. first);
- last = (EditText) findViewById(R.id. last);
- presenter = new UserPresenter( this);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id. save:
- presenter.saveUser(getID(), getFristName(), getLastName());
- break;
- case R.id. load:
- presenter.loadUser(getID());
- break;
- default:
- break;
- }
- }
- @Override
- public int getID() {
- return new Integer( id.getText().toString());
- }
- @Override
- public String getFristName() {
- return first.getText().toString();
- }
- @Override
- public String getLastName() {
- return last.getText().toString();
- }
- @Override
- public void setFirstName(String firstName) {
- first.setText(firstName);
- }
- @Override
- public void setLastName(String lastName) {
- last.setText(lastName);
- }
- }
2. 类目录结构
- 3. model接口和实现
- public interface INetConnect {
- boolean isNetConnect( Context context);
- }
- public class NetConnect implements INetConnect {
- @Override
- public boolean isNetConnect(Context context) {
- if (context != null) {
- ConnectivityManager mConnectivityManager = (ConnectivityManager) context
- .getSystemService(Context. CONNECTIVITY_SERVICE);
- NetworkInfo mNetworkInfo = mConnectivityManager
- .getActiveNetworkInfo();
- if (mNetworkInfo != null) {
- return mNetworkInfo.isAvailable();
- }
- }
- return false;
- }
- }
- 4. view接口
- public interface ISplashView {
- void showProcessBar();
- void hideProcessBar();
- void showNetError();
- void startNextActivity();
- }
- 5. presenter实现
- public class SplashPresenter {
- private INetConnect connect;
- private ISplashView iView;
- public SplashPresenter(ISplashView iView){
- this. iView = iView;
- connect = new NetConnect();
- }
- public void didFinishLoading(Context context){
- iView.showProcessBar();
- if( connect.isNetConnect(context)){
- iView.startNextActivity();
- } else{
- iView.showNetError();
- }
- iView.hideProcessBar();
- }
- }
- 6.activity中代码
- public class MainActivity extends Activity implements ISplashView{
- SplashPresenter presenter;
- private ProgressDialog progressBar;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout. activity_main);
- presenter = new SplashPresenter( this);
- }
- @Override
- protected void onResume() {
- super.onResume();
- presenter.didFinishLoading( this);
- }
- @Override
- public void showProcessBar() {
- if ( progressBar == null) {
- progressBar = new ProgressDialog( this);
- progressBar.setCancelable( true);
- progressBar.setCanceledOnTouchOutside( true);
- progressBar.setMessage( "更新数据中,请稍后" );
- }
- progressBar.show();
- }
- @Override
- public void hideProcessBar() {
- progressBar.hide();
- }
- @Override
- public void showNetError() {
- Toast. makeText(this, "暂无网络", Toast.LENGTH_SHORT).show();
- }
- @Override
- public void startNextActivity() {
- Toast. makeText(this, "跳到下个activity", Toast.LENGTH_SHORT).show();
- }
==========
MVP模式简单实例
一个简单的登录界面(实在想不到别的了╮( ̄▽ ̄")╭),点击LOGIN则进行账号密码验证,点击CLEAR则重置输入。
项目结构看起来像是这个样子的,MVP的分层还是很清晰的。我的习惯是先按模块分Package,在模块下面再去创建model、view、presenter的子Package,当然也可以用model、view、presenter作为顶级的Package,然后把所有的模块的model、view、presenter类都到这三个顶级Package中,就好像有人喜欢把项目里所有的Activity、Fragment、Adapter都放在一起一样。
首先来看看LoginActivity
public class LoginActivity extends ActionBarActivity implements ILoginView, View.OnClickListener {
private EditText editUser;
private EditText editPass;
private Button btnLogin;
private Button btnClear;
ILoginPresenter loginPresenter;
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//find view
editUser = (EditText) this.findViewById(R.id.et_login_username);
editPass = (EditText) this.findViewById(R.id.et_login_password);
btnLogin = (Button) this.findViewById(R.id.btn_login_login);
btnClear = (Button) this.findViewById(R.id.btn_login_clear);
progressBar = (ProgressBar) this.findViewById(R.id.progress_login);
//set listener
btnLogin.setOnClickListener(this);
btnClear.setOnClickListener(this);
//init
loginPresenter = new LoginPresenterCompl(this);
loginPresenter.setProgressBarVisiblity(View.INVISIBLE);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_login_clear:
loginPresenter.clear();
break;
case R.id.btn_login_login:
loginPresenter.setProgressBarVisiblity(View.VISIBLE);
btnLogin.setEnabled(false);
btnClear.setEnabled(false);
loginPresenter.doLogin(editUser.getText().toString(), editPass.getText().toString());
break;
}
}
@Override
public void onClearText() {
editUser.setText("");
editPass.setText("");
}
@Override
public void onLoginResult(Boolean result, int code) {
loginPresenter.setProgressBarVisiblity(View.INVISIBLE);
btnLogin.setEnabled(true);
btnClear.setEnabled(true);
if (result){
Toast.makeText(this,"Login Success",Toast.LENGTH_SHORT).show();
startActivity(new Intent(this, HomeActivity.class));
}
else
Toast.makeText(this,"Login Fail, code = " + code,Toast.LENGTH_SHORT).show();
}
@Override
public void onSetProgressBarVisibility(int visibility) {
progressBar.setVisibility(visibility);
}
}
从代码可以看出LoginActivity只做了findView以及setListener的工作,而且包含了一个ILoginPresenter,所有业务逻辑都是通过调用ILoginPresenter的具体接口来完成。所以LoginActivity的代码看起来很舒爽,甚至有点愉♂悦呢 (/ω\*)。视力不错的你可能还看到了ILoginView接口的实现,如果不懂为什么要这样写的话,可以先往下看,这里只要记住LoginActivity实现了ILoginView接口。
再来看看ILoginPresenter
public interface ILoginPresenter {
void clear();
void doLogin(String name, String passwd);
void setProgressBarVisiblity(int visiblity);
}
public class LoginPresenterCompl implements ILoginPresenter {
ILoginView iLoginView;
IUser user;
Handler handler;
public LoginPresenterCompl(ILoginView iLoginView) {
this.iLoginView = iLoginView;
initUser();
handler = new Handler(Looper.getMainLooper());
}
@Override
public void clear() {
iLoginView.onClearText();
}
@Override
public void doLogin(String name, String passwd) {
Boolean isLoginSuccess = true;
final int code = user.checkUserValidity(name,passwd);
if (code!=0) isLoginSuccess = false;
final Boolean result = isLoginSuccess;
handler.postDelayed(new Runnable() {
@Override
public void run() {
iLoginView.onLoginResult(result, code);
}
}, 3000);
}
@Override
public void setProgressBarVisiblity(int visiblity){
iLoginView.onSetProgressBarVisibility(visiblity);
}
private void initUser(){
user = new UserModel("mvp","mvp");
}
}
从代码可以看出,LoginPresenterCompl保留了ILoginView的引用,因此在LoginPresenterCompl里就可以直接进行UI操作了,而不用在Activity里完成。这里使用了ILoginView引用,而不是直接使用Activity,这样一来,如果在别的Activity里也需要用到相同的业务逻辑,就可以直接复用LoginPresenterCompl类了(一个Activity可以包含一个以上的Presenter,总之,需要什么业务就new什么样的Presenter,是不是很灵活(@ ̄︶ ̄@)),这也是MVP的核心思想
通过IVIew和IPresenter,把Activity的
UI Logic
和Business Logic
分离开来,Activity just does its basic job! 至于Model嘛,还是原来MVC里的Model。
再来看看ILoginView,至于ILoginView的实现类呢,翻到上面看看LoginActivity吧
public interface ILoginView {
public void onClearText();
public void onLoginResult(Boolean result, int code);
public void onSetProgressBarVisibility(int visibility);
}
代码这种东西放在日志里讲好像除了把整个版面拉长没什么卵用,我把几种自己常用的MVP的写法写成一个Demo项目,欢迎围观和PullRequest:Android-MVP-Pattern。
==========