最近在学习mvp设计模式,所以就拿以前写的一个Demo进行了改造。
源码如下:https://download.csdn.net/download/mei_jia12/10736932
UI界面:
该Demo涉及到的库和框架:
- MVP设计模式
- ButterKnife注入式框架
- RxJava+Retrofit组合的网络请求框架
- GreenDao数据库框架
- 阿里的Arouter路由框架,用于页面跳转
- Glide图片加载框架
- 腾讯Bugly
MVP的设计模式
MVP模式(Model-View-Presenter)发展自Android最早的MVC模式,虽然在原来的基础上很大程度的增加了类的数量和代码量,但是让Activity的代码变得更加简洁,分离了视图逻辑和业务逻辑,降低了耦合等等。
- Model层: 就是JavaBean实体类,用于保存实例数据
- View层: 就是程序的UI界面,用于向用户展示数据以及接收用户的输入
- Presenter层: 把所有业务逻辑的接口都放在这里。
eg 工程目录:
调用流程:LoginActivity通过调用ILoginPresenter接口中的方法,然而LoginPresenter实现了接口中的方法,业务逻辑就在实现的方法中。然后在LoginPresenter中调用接口ILoginView中的方法,而LoginActivity实现了ILoginView中的方法。这样就实现了双向调用
Model层是在LoginPresenter中被调用,完全和View层分隔开
代码如下:
Model层:
package example.com.vhdemo.mvp.model;
/**
* 登陆后返回
*/
public class LoginResponse {
/**
* DT : 2018-10-19 17:31:28
* Description : Success
* Result : 0
* data : {"code":"Add","crdate":"19:15","email":"","enable":"1","flag":"000000000000000000000000000000","key":"100099","loginid":"hka","name":"胡可","remark":"似懂非懂"}
* offset : 20
* secret : null
* sessionid : 似懂非懂
* token : 965A18C36CA574E701684E3C7F6E9312C31DE57910D9A7406F9457393C3B05E589B9F3F3858F9FB2167EB080919CA472
*/
private String DT;
private String Description;
private int Result;
private DataBean data;
private String offset;
private Object secret;
private String sessionid;
private String token;
public String getDT() {
return DT;
}
public void setDT(String DT) {
this.DT = DT;
}
public String getDescription() {
return Description;
}
public void setDescription(String Description) {
this.Description = Description;
}
public int getResult() {
return Result;
}
public void setResult(int Result) {
this.Result = Result;
}
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public String getOffset() {
return offset;
}
public void setOffset(String offset) {
this.offset = offset;
}
public Object getSecret() {
return secret;
}
public void setSecret(Object secret) {
this.secret = secret;
}
public String getSessionid() {
return sessionid;
}
public void setSessionid(String sessionid) {
this.sessionid = sessionid;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public static class DataBean {
/**
* code : Add
* crdate : 19:15
* email :
* enable : 1
* flag : 000000000000000000000000000000
* key : 100099
* loginid : hka
* name : 胡可
* remark : 似懂非懂
*/
private String code;
private String crdate;
private String email;
private String enable;
private String flag;
private String key;
private String loginid;
private String name;
private String remark;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getCrdate() {
return crdate;
}
public void setCrdate(String crdate) {
this.crdate = crdate;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getEnable() {
return enable;
}
public void setEnable(String enable) {
this.enable = enable;
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getLoginid() {
return loginid;
}
public void setLoginid(String loginid) {
this.loginid = loginid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}
}
View层
- 接口代码
package example.com.vhdemo.mvp.view;
public interface ILoginView {
void onClearEdit();
void onLoginResult(boolean isLogin);
}
- Activity中的代码
package example.com.vhdemo.mvp.view;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import example.com.vhdemo.R;
import example.com.vhdemo.base.CommonParameters;
import example.com.vhdemo.db.bean.User;
import example.com.vhdemo.db.help.UseHelper;
import example.com.vhdemo.mvp.presenter.LoginPresenter;
@Route(path = CommonParameters.Activity_Login)
public class LoginActivity extends AppCompatActivity implements ILoginView {
private static final String TAG = "LoginActivity";
@BindView(R.id.account)
EditText account;
@BindView(R.id.password)
EditText password;
@BindView(R.id.bt_enter)
Button btEnter;
LoginPresenter loginPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
loginPresenter=new LoginPresenter(this);
initView();
}
private void initView(){
User user=UseHelper.getInstance().getUser();
Log.e(TAG,"用户名:"+user.getName()+"\n"+"密码:"+user.getPassword());
account.setText(user.getName());
password.setText(user.getPassword());
}
@OnClick(R.id.bt_enter)
public void onViewClicked() {
Log.e(TAG,"点击了登陆!");
String name=account.getText().toString().trim();
String passWord=password.getText().toString().trim();
if (!name.equals("")&&!passWord.equals("")){
loginPresenter.doLogin(name,passWord); //通过P层来进行逻辑操作
// List<User>users=UseHelper.getInstance().getUsersList();
// Log.e(TAG,"用户数量:"+users.size()+users.get(1)); 测试bugly
}else {
Toast.makeText(LoginActivity.this,"账号或者密码不为空",Toast.LENGTH_SHORT).show();
}
}
@Override
public void onClearEdit() {
password.setText("");
}
@Override
public void onLoginResult(boolean isLogin) {
if (isLogin){
ARouter.getInstance().build(CommonParameters.Activity_Main).navigation();
Toast.makeText(LoginActivity.this,"登陆成功",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(LoginActivity.this,"登陆失败",Toast.LENGTH_SHORT).show();
}
}
}
Presenter层代码
- 接口中代码
package example.com.vhdemo.mvp.presenter;
public interface ILoginPresenter {
void doLogin(String name,String password);
}
- 实现接口类中的代码
package example.com.vhdemo.mvp.presenter;
import android.util.Log;
import example.com.vhdemo.db.bean.User;
import example.com.vhdemo.db.help.UseHelper;
import example.com.vhdemo.mvp.model.LoginResponse;
import example.com.vhdemo.mvp.view.ILoginView;
import example.com.vhdemo.net.LoginManage;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
public class LoginPresenter implements ILoginPresenter {
private static final String TAG = "LoginPresenter";
private String name,password;
ILoginView mILoginView;
public LoginPresenter(ILoginView iLoginView) {
super();
this.mILoginView=iLoginView;
}
@Override
public void doLogin(final String name, final String password) {
this.name=name;
this.password=password;
LoginManage.getLoginServer().doLogin("Login",name,password)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Observer<LoginResponse>() {
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG,"onSubscribe");
}
@Override
public void onNext(LoginResponse loginResponse) {
Log.e(TAG,"请求结果:"+loginResponse.getDescription());
if (loginResponse.getResult()==0){
mILoginView.onLoginResult(true);
User user=new User();
user.setName(name);
user.setPassword(password);
UseHelper.getInstance().addUser(user); //如果登录成功则保存账号密码
}else {
mILoginView.onLoginResult(false);
mILoginView.onClearEdit();
}
}
@Override
public void onError(Throwable e) {
Log.e(TAG,"e="+e);
}
@Override
public void onComplete() {
Log.e(TAG,"onComplete");
}
});
}
}
RxJava+Retrofit网络请求的封装
package example.com.vhdemo.net;
import android.util.Log;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import example.com.vhdemo.mvp.model.LoginResponse;
import example.com.vhdemo.util.DateUtils;
import example.com.vhdemo.util.JsonHandleUtils;
import io.reactivex.Observable;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.POST;
import retrofit2.http.Query;
/**
* 网络请求类
*/
public class LoginManage {
private static final String TAG = "LoginManage";
private static long CONNECT_TIMEOUT = 60L;
private static long READ_TIMEOUT = 30L;
private static long WRITE_TIMEOUT = 30L;
private static final String baseUrl="http://112.124.5.152:8096/WSMobile.ashx/";
private static LoginServer loginServer;
public interface LoginServer{
/**
* 登陆接口
* @param action
* @param uid
* @param pwd
* @return
*/
@POST("?")
Observable<LoginResponse> doLogin(@Query("action") String action, @Query("uid") String uid, @Query("pwd") String pwd);
}
/**
* 单例模式
* 创建接口实例
* @return
*/
public static LoginServer getLoginServer(){
if (loginServer==null){
synchronized (LoginServer.class){
if (loginServer==null){
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(baseUrl)
.client(getOkHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
loginServer=retrofit.create(LoginServer.class);
}
}
}
return loginServer;
}
/**
* 获取OkHttpClient实例
* @return
*/
private static OkHttpClient getOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(new RqInterceptor())
.addInterceptor(new LogInterceptor())
.build();
return okHttpClient;
}
/**
* 请求拦截器
*/
private static class RqInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.addHeader("X-APP-TYPE","android")
.build();
Response response = chain.proceed(request);
return response;
}
}
/**
* 日志拦截器
*/
private static class LogInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
String url = request.url().toString();
String params = requestBodyToString(request.body());
Response response = chain.proceed(request);
String responseString = JsonHandleUtils.jsonHandle(response.body().string());
String time = DateUtils.getNowDateFormat(DateUtils.DATE_FORMAT_2);
String log = "\n\n*****请求时间*****:\n" + time+"\n*******路径*******:\n" + url + "\n*******参数*******:\n" + params + "\n*******报文*******:\n" + responseString+"\n \n";
Log.d(TAG,log);
return chain.proceed(request);
}
}
private static String requestBodyToString(final RequestBody request) {
try {
final RequestBody copy = request;
final Buffer buffer = new Buffer();
if (copy != null){
copy.writeTo(buffer);
}
else{
return "";
}
return buffer.readUtf8();
} catch (final IOException e) {
return "did not work";
}
}
}
结束