转载请注明出处:http://blog.csdn.net/tyhj_sf/article/details/52822514
前言
本文不会逐个讲解MVP、Rxjava、Retrofit、GreenDAO的使用方法,而是结合app的用户注册登录功能的DEMO代码综讲解实际开发中如何综合使用。相信你认真分析和运行这个Demo之后,就可以上手用在你的项目中了。
关于MVP模式的详细介绍,可以参见:
MVC、MVP、MVVM深入理解与使用
各层之间的解耦使用Rxjava,关于Rxjava的详细使用方法,强烈推荐:
给 Android 开发者的 RxJava 详解
网络的访问使用Retrofit关于Retrofit的使用方法,推荐:
Retrofit用法详解
数据库存取使用GreenDAO开源库,关于GreenDAO的简单使用可以参考:
GreenDAO 3.2官方给的例子
Android数据存储之GreenDao 3.0 详解
项目搭建
1.MVP模式的package 结构
2.在gradle文件添加项目使用的第三方包的依赖关系
修改project的build.gradle文件如下:
在Module的build.gradle中添加使用的包和插件:
修改的地方如下图:
MVP框架之View层
实现APP的用户注册功能,界面如下图:
(layout文件就不贴出来了,整个DEMO的源码的链接我已经放在文章的结尾。)
View层的相关类
这里我们以SignOnFragment类为例来说,SignOnFragment类本身是一个Fragment,我们把它当做MVP模式中V,activity用来控制组件的生存周期,这是Google官方推荐的用法,但是Fragment必须内嵌到activity中显示,并且fragmen的使用也使组件生存周期和组件间通信变得复杂。对于不太复杂的应用,其实我们完全可以把activity看做是MVP中的V,显示逻辑写在activity中丢弃fragment,这样看起来代码结构更简洁。
SignOnFragment类文件代码如下:
public class SignOnFragment extends android.app.Fragment implements SignOnFragmentInterface {
private EditText mUsername;
private EditText mUserPassword1;
private EditText mUserPassword2;
private EditText mEmailAddress;
private Button mRegister;
private ProgressDialog progressDialog;
private SignOnLogic signOnLogicInterface;
/**供系统调用*/
public SignOnFragment() {
// Required empty public constructor
}
public static SignOnFragment newInstance(){
return new SignOnFragment();
}
public SignOnLogic getSignOnLogicInterface() {
return signOnLogicInterface;
}
public void setSignOnLogicInterface(SignOnLogic signOnLogicInterface) {
this.signOnLogicInterface = signOnLogicInterface;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_sign_on, container, false);
mUsername=(EditText) view.findViewById(R.id.register_name);
mEmailAddress=(EditText) view.findViewById(R.id.register_email);
mUserPassword1=(EditText)view.findViewById(R.id.register_password1);
mUserPassword2=(EditText)view.findViewById(R.id.register_password2);
mRegister =(Button)view.findViewById(R.id.register_register);
mRegister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
signOnLogicInterface.authority(getSignOnInfo());
}
});
progressDialog=new ProgressDialog(getActivity());
return view;
}
@Override
public void onDestroy() {
if (progressDialog!=null){
progressDialog.dismiss();
}
super.onDestroy();
}
@Override
public void onDetach() {
super.onDetach();
}
void updateView(Map<String, Object> map){
}
@Override
public Map<String, Object> getSignOnInfo(){
Map<String,Object> map=new HashMap<String,Object>();
map.put("mUserName",mUsername.getText().toString());
map.put("mUserPassword1",mUserPassword1.getText().toString());
map.put("mUserPassword2",mUserPassword2.getText().toString());
map.put("mEmailAddress",mEmailAddress.getText().toString());
return map;
}
@Override
public void showCheckError(String result) {
Toast.makeText(getActivity(),result,Toast.LENGTH_SHORT).show();
}
@Override
public void showErrorByToast(String result) {
Toast.makeText(getActivity(),result,Toast.LENGTH_SHORT).show();
}
@Override
public void showProgressDialog() {
progressDialog.setIndeterminate(true);
progressDialog.setMessage("正在注册....");
progressDialog.show();
}
@Override
public void dismissProgressDialog() {
progressDialog.dismiss();
}
@Override
public void gotoSignInView() {
getActivity().startActivity(new Intent(getActivity(), SignInActivity.class));
}
}
只需坚持一条原则,View层代码中不含有任何处理逻辑及model的逻辑,而只有显示逻辑。
MVP框架之Model层
model层我们在这里只定义一个实体类:User,其代码如下:
package com.example.mvp_demo.model;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.NotNull;
import org.greenrobot.greendao.annotation.Generated;
/**
*
* Created by hasee on 2016/8/22.
*/
@Entity
public class User extends BasicEntity {
@Id(autoincrement = true)
public Long id;
@NotNull
public String mUsername;
public String mUserPassword;
public String mEmailAddress;
public User(){
}
@Generated(hash = 594399851)
public User(Long id, @NotNull String mUsername, String mUserPassword, String mEmailAddress) {
this.id = id;
this.mUsername = mUsername;
this.mUserPassword = mUserPassword;
this.mEmailAddress = mEmailAddress;
}
@Override
public String toString() {
return super.toString()+",[mUsername]="+mUsername+",[mUserPassword]="+mUserPassword+",[mEmailAddress]="+mEmailAddress;
}
@Override
public boolean equals(User obj) {
return mUsername.equals(obj.mUsername);
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getMUsername() {
return this.mUsername;
}
public void setMUsername(String mUsername) {
this.mUsername = mUsername;
}
public String getMUserPassword() {
return this.mUserPassword;
}
public void setMUserPassword(String mUserPassword) {
this.mUserPassword = mUserPassword;
}
public String getMEmailAddress() {
return this.mEmailAddress;
}
public void setMEmailAddress(String mEmailAddress) {
this.mEmailAddress = mEmailAddress;
}
}
由于我们使用了GreenDao数据库ORM框架,因此实际上我们只需要定义清楚如下图红线框部分,注解清楚哪些成员变量我们需要映射到数据库中,其他的代码在gradle时,有GreenDao框架自动生成:
MVP框架之Presenter层
最关键的部分来了。
对于注册功能,presenter层类有如下两个:
先贴SignOnLogicImpl类的代码:
public class SignOnLogicImpl implements SignOnLogic {
public SignOnFragmentInterface signOnFragmentInterface;
public SignOnLogicImpl(SignOnFragmentInterface signOnFragmentInterface) {
this.signOnFragmentInterface = signOnFragmentInterface;
}
public void setSignOnFragmentInterface(SignOnFragmentInterface signOnFragmentInterface) {
this.signOnFragmentInterface = signOnFragmentInterface;
}
public SignOnFragmentInterface getSignOnFragmentInterface() {
return signOnFragmentInterface;
}
protected boolean checkInput(Map<String, Object> userInfoMap) {
String inputInfo = userInfoMap.get("mUserName").toString();
String checkResult = null;
if (inputInfo.trim().length() == 0) {
checkResult = "用户名不能为空";
} else if (inputInfo.length() < 6) {
checkResult = "用户名太短";
} else if (inputInfo.length() > 30) {
checkResult = "用户名太长";
} else if (!userInfoMap.get("mEmailAddress").toString().matches("[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}")) {
checkResult = "邮箱格式错误,请检查";
} else if (userInfoMap.get("mUserPassword1").toString().length() < 6) {
checkResult = "密码太短";
} else if (userInfoMap.get("mUserPassword1").toString().length() > 30) {
checkResult = "密码太长";
} else if (!userInfoMap.get("mUserPassword1").toString().equals(userInfoMap.get("mUserPassword2").toString())) {
checkResult = "两次输入的密码不一致,请重新输入";
}
if (checkResult != null) {
signOnFragmentInterface.showCheckError(checkResult);
return false;
}
return true;
}
@Override
public void authority(Map<String, Object> userInfoMap) {
// boolean isSuccess=false;
if (!checkInput(userInfoMap)) {
return ;
}
final User user = new User();
user.mUsername = userInfoMap.get("mUserName").toString();
user.mUserPassword = userInfoMap.get("mUserPassword1").toString();
user.mEmailAddress = userInfoMap.get("mEmailAddress").toString();
signOnFragmentInterface.showProgressDialog();
new Retrofit.Builder()
.baseUrl(MyApplication.BASIC_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(Server.class)
.uploadUser(user) //上传注册信息
.doOnNext(new Action1<String>() {
@Override
public void call(String s) {
if (s.equals("success")) {
//保存用户注册信息到客户端数据库
GreenDaoManager
.getInstance()
.getmDaoSession()
.getUserDao()
.insert(user);
Log.d("数据库测试", "保存user成功");
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
signOnFragmentInterface.dismissProgressDialog();
}
@Override
public void onError(Throwable e) {
signOnFragmentInterface.dismissProgressDialog();
signOnFragmentInterface.showErrorByToast("网络发生错误:" + e.toString());
}
@Override
public void onNext(String s) {
if (s.equals("success")) {
//界面跳转到
signOnFragmentInterface.gotoSignInView();
} else {
signOnFragmentInterface.showErrorByToast("服务端响应错误");
}
}
});
}
}
这里protected boolean checkInput(Map<String, Object> userInfoMap)
无非是对用户输入信息进行格式校验。
这里的public void authority(Map<String, Object> userInfoMap)
用于向服务器端请求并向界面输出服务端认证结果。
我们着重看这部分代码:
new Retrofit.Builder()
.baseUrl(MyApplication.BASIC_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(Server.class)
.uploadUser(user) //上传注册信息
.doOnNext(new Action1<String>() {
@Override
public void call(String s) {
if (s.equals("success")) {
//保存用户注册信息到客户端数据库
//。。。。。省略。。。。。
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
// 。。。。。省略。。。。。
}
@Override
public void onError(Throwable e) {
//。。。。。省略。。。。。
}
@Override
public void onNext(String s) {
// 。。。。。省略。。。。。。
}
}
});
由于Retrofit库已经为RxJava做了适配,这里我把Retrofit访问服务器的接口函数与RxJava的Observable结合起来,即uploadUser()函数返回Observable<String>
类型对象,实现了很流畅的函数响应式编程。
Retrofit访问网络的接口如下:
如果不使用RxJava,那么Retrofit的网络接口定义应该是这样的:
@GET("account")
Call<String> uploadUser(@Query("username") User user);
项目整体上已经粗略讲解完毕。只看源码,不如亲自试试运行一个完整的DEMO理解得透彻!
附上源码下载链接:MVP+RxJava+Retrofit+GreenDao的Demo源码