RxJava+Retrofit+MVP的实践小结

最近在学习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";
        }
    }

}

结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值