Android MVP 架构示例
来源:互联网 发布:日本黑社会电影知乎 编辑:程序博客网 时间:2024/04/28 20:02
首先说明:这篇博客参考资料 鸿神的MVP博客 内容上有着很大的相似性。
如果是比较初级的读者,只是开始接触MVP,我建议可以看一下我的另外两个博客,个人认为对理解MVP有帮助而写的比较不美观的博客
一、 MVP前奏(一)接口
二、MVP前奏(二)MVC在Android的小短腿
我觉得编程这个东西,开始不一定非要深入,只要先上手使用就好了,用着用着,认识会随着熟练度增长,有了一定的熟练度后再去深入研究问题,也能事半功倍了。
做个说明:ui包的activity几乎都继承了view中定义的接口,ui是属于V的;
biz包定义了接口和实际操作,OnloginListener是登录的回调接口,属于P层;
M层只有一个model;
至于base包,请忽略。
开始正文:
这个demo使用MVP实现了两点小功能
1.realm存一个用户信息;
2.Rxjava模拟登录。
最简单的M开始,只定义了用户模型User,因为要使用realm存储,所以User继承了RealmObject:
<span style="font-size:18px;">package com.hcsw.newtecset.model;import io.realm.RealmObject;/** * Created by Administrator on 2016/3/9. */public class User extends RealmObject{ 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; }}</span>
我的一篇关于Realm的简单博客
由IRealmView定义RealmActivity需要实现的功能,将来IRealmView会作为RealmActivity的代表参与操作:
<span style="font-size:18px;">package com.hcsw.newtecset.view;/** * Created by Administrator on 2016/3/10. */public interface IRealmView { String getUserName();//获取输入的用户名 String getPassword();//获取输入的密码 void toLoginActivity();//添加成功后的操作 void showTip(String tip);//关闭Realm}</span>
关于BaseActivity的代码稍后贴出。
<span style="font-size:18px;">package com.hcsw.newtecset.ui;import android.content.Intent;import android.view.View;import android.widget.EditText;import android.widget.LinearLayout;import android.widget.Toast;import com.hcsw.newtecset.R;import com.hcsw.newtecset.base.BaseActivity;import com.hcsw.newtecset.presenter.RealmPresenter;import com.hcsw.newtecset.view.IRealmView;public class RealmActivity extends BaseActivity implements IRealmView { private EditText edtName,edtPwd; private RealmPresenter presenter; @Override public int getContentViewId() { return R.layout.activity_main; } @Override public int getTitleBarId() { return -1; } @Override protected String getActivityTitleTxt() { return "设置用户信息"; } @Override protected void initIntent() { } @Override public void initComponents() { setTitleBarAction(); findViewById(R.id.title_bar_left_area).setVisibility(View.INVISIBLE); presenter = new RealmPresenter(this); edtName = (EditText) findViewById(R.id.edt_username); edtPwd = (EditText) findViewById(R.id.edt_password); findViewById(R.id.btn_save).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { presenter.insertUser(); } }); } @Override public void loadData() { } @Override public boolean isResumeLoad() { return false; } @Override protected void onDestroy() { super.onDestroy(); presenter.closeRealm(); } @Override public String getUserName() { return edtName.getText().toString(); } @Override public String getPassword() { return edtPwd.getText().toString(); } @Override public void toLoginActivity() { startActivity(new Intent(this,LoginActivity.class)); } @Override public void showTip(String tip) { Toast.makeText(this,tip,Toast.LENGTH_LONG).show(); }}</span>由ILoginView定义LoginActivity需要实现的功能,将来ILoginView会作为LoginActivity的代表参与操作:
package com.hcsw.newtecset.view;/** * Created by Administrator on 2016/3/9. */public interface IUserLoginView { String getUserName();//获取账号 String getPassword();//获取密码 void cleanUserName();//清除账号 void cleanPassword();//清除密码,两个可以合并为一个清楚方法 void showLoading();//显示表示“登录中”的progressbar void hideLoading();//隐藏表示“登录中”的progressbar void onLoginSuccess();//处理登录成功的方法 void onLoginFailed();//处理登录失败的方法}
package com.hcsw.newtecset.ui;import android.app.ProgressDialog;import android.content.Intent;import android.view.View;import android.widget.EditText;import android.widget.ProgressBar;import android.widget.Toast;import com.hcsw.newtecset.R;import com.hcsw.newtecset.base.BaseActivity;import com.hcsw.newtecset.presenter.LoginPresenter;import com.hcsw.newtecset.view.IUserLoginView;/** * Created by Administrator on 2016/3/9. */public class LoginActivity extends BaseActivity implements IUserLoginView{ ProgressBar pLoading; LoginPresenter presenter; private EditText edtName,edtPwd; @Override public int getContentViewId() { return R.layout.activity_login; } @Override public int getTitleBarId() { return -1; } @Override protected String getActivityTitleTxt() { return "登录"; } @Override protected void initIntent() { } @Override public void initComponents() { presenter = new LoginPresenter(this); setTitleBarAction(); findViewById(R.id.title_bar_left_area).setVisibility(View.INVISIBLE); edtName = (EditText) findViewById(R.id.edt_username); edtPwd = (EditText) findViewById(R.id.edt_password); pLoading = (ProgressBar) findViewById(R.id.pb_loading); findViewById(R.id.btn_login).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { presenter.login(); } }); findViewById(R.id.btn_clean).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { presenter.clear(); } }); } @Override public void loadData() { } @Override public boolean isResumeLoad() { return false; } @Override public String getUserName() { return edtName.getText().toString(); } @Override public String getPassword() { return edtPwd.getText().toString(); } @Override public void cleanUserName() { edtName.setText(""); } @Override public void cleanPassword() { edtPwd.setText(""); } @Override public void showLoading() { pLoading.setVisibility(View.VISIBLE); } @Override public void hideLoading() { pLoading.setVisibility(View.GONE); } @Override public void onLoginSuccess() { Toast.makeText(this,"Success",Toast.LENGTH_LONG).show(); startActivity(new Intent(this,SecondActivity.class)); } @Override public void onLoginFailed() { Toast.makeText(this,"failed",Toast.LENGTH_LONG).show(); }}
再接下来是P层
为Realm和登录分别创建接口IRealmBiz和IUserBiz,定义需要实现的内容方法。
IRealmBiz定义了增、删、改、查和关闭数据库五个方法,由RealmBiz继承实现:
<span style="font-size:18px;">package com.hcsw.newtecset.biz;import com.hcsw.newtecset.model.User;/** * Created by Administrator on 2016/3/10. */public interface IRealmBiz { void insertRealm(String name,String pwd); User selectRealm(); void deleteRealm(User user); void uploadRealm(User user); void closeRealm();}</span>
<span style="font-size:18px;">package com.hcsw.newtecset.biz;import com.hcsw.newtecset.model.User;import io.realm.Realm;/** * Created by Administrator on 2016/3/10. */public class RealmBiz implements IRealmBiz{ private Realm realm; public RealmBiz(){ realm = Realm.getDefaultInstance(); } @Override public void insertRealm(String name,String pwd) { realm.beginTransaction(); User user = realm.createObject(User.class); user.setUserName(name); user.setPassword(pwd); realm.commitTransaction(); } @Override public User selectRealm() { realm.beginTransaction(); User user = realm.where(User.class).findFirst(); realm.commitTransaction(); return user; } @Override public void deleteRealm(User user) { realm.beginTransaction(); realm.commitTransaction(); } @Override public void uploadRealm(User user) { realm.beginTransaction(); realm.commitTransaction(); } @Override public void closeRealm() { realm.beginTransaction(); realm.where(User.class).findAll().clear(); realm.commitTransaction(); realm.close(); }}</span>
关于realm = Realm.getDefaultInstance()这句,请参照后面贴出的MyApplication代码;
IUserBiz只定义了一个login方法,并设置了三个参数,由UserBiz继承实现,OnloginListener是作为登录结果监听的接口,只有成功和失败两个方法:
<span style="font-size:18px;">package com.hcsw.newtecset.biz;/** * Created by Administrator on 2016/3/9. */public interface IUserBiz { void login(String name,String password,OnloginListener listener);}</span>这里用到了一些Rxjava的语法。
<span style="font-size:18px;">package com.hcsw.newtecset.biz;import com.hcsw.newtecset.model.User;import java.util.concurrent.TimeUnit;import io.realm.Realm;import rx.Observable;import rx.Observable.OnSubscribe;import rx.Observer;import rx.Subscriber;import rx.android.schedulers.AndroidSchedulers;import rx.functions.Action1;import rx.functions.Func1;import rx.schedulers.Schedulers;/** * Created by Administrator on 2016/3/9. */public class UserBiz implements IUserBiz{ @Override public void login(final String name, final String password, final OnloginListener listener) { Observable .create(new OnSubscribe<Boolean>() { @Override public void call(Subscriber<? super Boolean> subscriber) { Realm realm = Realm.getDefaultInstance(); User user = realm.where(User.class).findFirst(); String u = user.getUserName(); String p =user.getPassword(); boolean b = u.equals(name)&&p.equals(password); subscriber.onNext(b); } }) .subscribeOn(Schedulers.io()) .delay(2, TimeUnit.SECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Boolean>() { @Override public void call(Boolean aBoolean) { if(aBoolean){ User user = new User(); user.setUserName(name); user.setPassword(password); listener.loginSuccess(user); }else{ listener.loginFailed(); } } }); }}</span>
<span style="font-size:18px;">package com.hcsw.newtecset.biz;import com.hcsw.newtecset.model.User;/** * Created by Administrator on 2016/3/9. */public interface OnloginListener { void loginSuccess(User user); void loginFailed();}</span>
代码关联处理关系整合的关键类,接下来的类就如同是交通枢纽,将整个结构联系起来:
<span style="font-size:18px;">package com.hcsw.newtecset.presenter;import com.hcsw.newtecset.biz.RealmBiz;import com.hcsw.newtecset.view.IRealmView;/** * Created by Administrator on 2016/3/10. */public class RealmPresenter { private RealmBiz realmBiz; //代理处理RealmActivity中的方法 private IRealmView iRealmActivity; public RealmPresenter(IRealmView iActivity){ realmBiz = new RealmBiz(); iRealmActivity = iActivity; } public void insertUser(){ //参数通过iRealmActivity获取RealmActivity中的实际值 realmBiz.insertRealm(iRealmActivity.getUserName(),iRealmActivity.getPassword()); //结果返回RealmActivity处理 iRealmActivity.showTip("插入数据完成"); iRealmActivity.toLoginActivity(); } //关闭数据库 public void closeRealm(){ realmBiz.closeRealm(); }}</span>
<span style="font-size:18px;">package com.hcsw.newtecset.presenter;import com.hcsw.newtecset.biz.OnloginListener;import com.hcsw.newtecset.biz.UserBiz;import com.hcsw.newtecset.model.User;import com.hcsw.newtecset.view.IUserLoginView;import java.util.concurrent.TimeUnit;import rx.Observable;import rx.Subscriber;import rx.android.schedulers.AndroidSchedulers;import rx.functions.Action1;/** * Created by Administrator on 2016/3/9. */public class LoginPresenter { UserBiz userBiz; //LoginActivity的代表 IUserLoginView userLoginView; public LoginPresenter(IUserLoginView loginView){ this.userLoginView = loginView; userBiz = new UserBiz(); } public void login(){ userLoginView.showLoading(); userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnloginListener() { @Override public void loginSuccess(final User user) { //Rxjava的语法,在收到成功后执行 Observable .create(new Observable.OnSubscribe<User>() { @Override public void call(Subscriber<? super User> subscriber) { subscriber.onNext(user); } }) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<User>() { @Override public void call(User user) { userLoginView.hideLoading(); userLoginView.onLoginSuccess(); } }); } @Override public void loginFailed() { Observable .create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext(""); } }) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<String>() { @Override public void call(String user) { userLoginView.hideLoading(); userLoginView.onLoginFailed(); } }); } }); } public void clear(){ userLoginView.cleanUserName(); userLoginView.cleanPassword(); }}</span>
上一张MVC和MVP的区别图(图片原文):
我的手工图:
个人觉得这里最重要的就是通过接口的实现的各种调用。理解接口很重要
demo下载地址
- Android MVP 架构示例
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解析
- Android-----官方MVP架构----示例项目解析
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解读
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解析
- Android官方MVP架构示例项目解析
- Android MVP架构和MVC架构比较(有代码示例)
- 如何用Scapy写一个端口扫描器?
- #12V直流电源简单Get
- 在某一数值范围内取随机数
- PowerDesigner打开设计文件后提示failed to read the fileXXX的解决办法
- JavaScript中栈和队列相关操作和实现
- Android MVP 架构示例
- PAT (Top Level) Practise 1010Lehmer Code (35)
- React组件之间传值
- ListView中如何使用Button,让onClick和onItemClick事件共存
- 关于未来
- maven tomcat7:deploy
- Java高级开发反射手段更换对象根节点内容
- web进修之—Hibernate起步(1)
- Arcgis server发布切片替换之前的注意事项