OKhttp框架的MVP模式实现

本章节讲述MVP模式实现Okhttp框架

 

 

一.MVP模式

 

MVP作为MVC的演化,解决了MVC不少的缺点,对于Android来说,MVP的model层相对于MVC是一样的,而activity和fragment不再是controller层,而是纯粹的view层,所有关于用户事件的转发全部交由presenter层处理。下面还是让我们看图

 

OKhttp框架的MVP模式实现_第1张图片

 

 

从图中就可以看出,最明显的差别就是view层和model层不再相互可知,完全的解耦,取而代之的presenter层充当了桥梁的作用,用于操作view层发出的事件传递到presenter层中,presenter层去操作model层,并且将数据返回给view层,整个过程中view层和model层完全没有联系。看到这里大家可能会问,虽然view层和model层解耦了,但是view层和presenter层不是耦合在一起了吗?其实不是的,对于view层和presenter层的通信,我们是可以通过接口实现的。

具体的意思就是说我们的activity,fragment可以去实现实现定义好的接口,而在对应的presenter中通过接口调用方法。不仅如此,我们还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试。这就解决了MVC模式中测试,维护难的问题。

当然,其实最好的方式是使用fragment作为view层,而activity则是用于创建view层(fragment)和presenter层(presenter)的一个控制器。

和MVC最大的不同,MVP把activity作为了view层,通过代码也可以看到,整个activity没有任何和model层相关的逻辑代码,取而代之的是把代码放到了presenter层中,presenter获取了model层的数据之后,通过接口的形式将view层需要的数据返回给它就OK了。

这样的好处是。首先,activity的代码逻辑减少了,其次,view层和model层完全解耦,具体来说,如果你需要测试一个http请求是否顺利,你不需要写一个activity,只需要写一个java类,实现对应的接口,presenter获取了数据自然会调用相应的方法,相应的,你也可以自己在presenter中mock数据,分发给view层,用来测试布局是否正确。

 

 

详解:Android MVC MVP MVVM 模式

 

 

 

 

二.OKHttp+MVP

 

项目截图

OKhttp框架的MVP模式实现_第2张图片

 

 

 

以登录为例

 

M层代码 Model

 

1.常量 constant

 

设置 OKHttp网络超时时间 各个接口Url等等。 

 

 

2.OkHttpClient工具类

 

/**
 * Created by wjn on 2017/11/22.
 * OkHttp框架 封装方法
 */

public class RxAndroidOkhttp {

    private OkHttpClient mOkHttpClient = null;//OkHttpClient 对象
    private static RxAndroidOkhttp mRxAndroidOkhttp = null;//RxAndroidOkhttp 对象

    /**
     * 构造方法私有化
     */

    private RxAndroidOkhttp() {
        //创建okhttp对象 以及连接,读,取超时时间
        mOkHttpClient = new OkHttpClient.Builder()
                .connectTimeout(DataConstant.nettimeout, TimeUnit.SECONDS)//连接时间
                .readTimeout(DataConstant.nettimeout, TimeUnit.SECONDS)//读时间
                .writeTimeout(DataConstant.nettimeout, TimeUnit.SECONDS)//写时间
                .build();
    }

    /**
     * 获取此单例类对象的方法
     */

    public static RxAndroidOkhttp getInstance() {
        if (null == mRxAndroidOkhttp) {//单例对象为空
            synchronized (RxAndroidOkhttp.class) {
                mRxAndroidOkhttp = new RxAndroidOkhttp();
            }
        }
        return mRxAndroidOkhttp;
    }

    /**
     * get请求方法
     */

    public Observable get(final String url) {
        //创建被观察者
        Observable observable = Observable.create(new Observable.OnSubscribe() {
            @Override
            public void call(Subscriber subscriber) {
                final Subscriber mSubscriber = subscriber;
                //没有取消订阅的时候
                if (!mSubscriber.isUnsubscribed()) {
                    //get请求
                    Request request = null;
                    String cookie = MyApplication.getOkhttpCookie();
                    if (!BooleanUtils.isEmpty(cookie)) {
                        request = new Request.Builder()
                                .addHeader("cookie", cookie)
                                .url(url)
                                .get()
                                .build();
                    } else {
                        request = new Request.Builder()
                                .url(url)
                                .get()
                                .build();
                    }
                    if (null != mOkHttpClient) {
                        mOkHttpClient.newCall(request).enqueue(new Callback() {
                            @Override
                            public void onFailure(Call call, IOException e) {
                                //通知订阅者的错误信息
                                mSubscriber.onError(e);
                            }

                            @Override
                            public void onResponse(Call call, Response response) throws IOException {
                                if (null != response) {//response 不为空
                                    if (response.isSuccessful()) {//response 请求成功
                                        Headers headers = response.headers();
                                        List cookies = headers.values("Set-Cookie");
                                        if (cookies.size() > 0) {
                                            String session = cookies.get(0);
                                            String result = session.substring(0, session.indexOf(";"));
                                            MyApplication.setOkhttpCookie(result);
                                        }
                                        //通知订阅者的成功信息
                                        mSubscriber.onNext(response.body().string());
                                    } else {//response 请求失败
                                        //通知订阅者的错误信息
                                        IOException IOExceptionx = new IOException();
                                        mSubscriber.onError(IOExceptionx);
                                    }
                                } else {//response 为空
                                    //通知订阅者的错误信息
                                    IOException IOExceptionx = new IOException();
                                    mSubscriber.onError(IOExceptionx);
                                }
                                //通知完毕
                                mSubscriber.onCompleted();
                            }
                        });
                    }
                }
            }
        });
        return observable;
    }

    /**
     * post请求方法
     */

    public Observable post(final String url, final Map params) {
        //创建被观察者
        Observable observable = Observable.create(new Observable.OnSubscribe() {
            @Override
            public void call(Subscriber subscriber) {
                final Subscriber mSubscriber = subscriber;
                //没有取消订阅的时候
                if (!mSubscriber.isUnsubscribed()) {
                    //获取FormBody.Builder 对象
                    FormBody.Builder builder = new FormBody.Builder();
                    //遍历params 将其放入到FormBody.Builder 对象
                    if (params != null && !params.isEmpty()) {
                        for (Map.Entry entry : params.entrySet()) {
                            builder.add(entry.getKey(), entry.getValue());
                        }
                    }
                    //获取RequestBody 对象
                    RequestBody requestBody = builder.build();
                    //构建post请求
                    Request request = null;
                    String cookie = MyApplication.getOkhttpCookie();
                    if (!BooleanUtils.isEmpty(cookie)) {
                        request = new Request.Builder()
                                .addHeader("cookie", cookie)
                                .url(url)
                                .post(requestBody)
                                .build();
                    } else {
                        request = new Request.Builder()
                                .url(url)
                                .post(requestBody)
                                .build();
                    }
                    if (mOkHttpClient != null) {
                        mOkHttpClient.newCall(request).enqueue(new Callback() {
                            @Override
                            public void onFailure(Call call, IOException e) {
                                //通知订阅者的错误信息
                                mSubscriber.onError(e);
                            }

                            @Override
                            public void onResponse(Call call, Response response) throws IOException {
                                if (null != response) {//response 不为空
                                    if (response.isSuccessful()) {//response 请求成功
                                        Headers headers = response.headers();
                                        List cookies = headers.values("Set-Cookie");
                                        if (cookies.size() > 0) {
                                            String session = cookies.get(0);
                                            String result = session.substring(0, session.indexOf(";"));
                                            MyApplication.setOkhttpCookie(result);
                                        }
                                        //通知订阅者的成功信息
                                        mSubscriber.onNext(response.body().string());
                                    } else {//response 请求失败
                                        //通知订阅者的错误信息
                                        IOException IOExceptionx = new IOException();
                                        mSubscriber.onError(IOExceptionx);
                                    }
                                } else {//response 为空
                                    //通知订阅者的错误信息
                                    IOException IOExceptionx = new IOException();
                                    mSubscriber.onError(IOExceptionx);
                                }
                                //通知完毕
                                mSubscriber.onCompleted();
                            }
                        });
                    }
                }
            }
        });
        return observable;
    }

    /**
     * 自定义onError字符串(欢迎页面)
     */

    public static String getonErrorSplashString(Throwable e) {
        String result = StringConstant.Splashing3;
        if (null != e) {
            Throwable throwable = e.getCause();
            if (null != throwable) {
                if (throwable.equals(SocketTimeoutException.class)) {
                    result = StringConstant.Splashing5;
                }
            }

            String msg = e.getMessage();
            if (!BooleanUtils.isEmpty(msg) && msg.contains("timeout")) {
                result = StringConstant.Splashing5;
            }

        }

        return result;
    }

    /**
     * 自定义onError字符串(其他页面)
     */

    public static String getonErrorOtherString(Throwable e) {
        String result = StringConstant.errorstate1;
        if (null != e) {
            Throwable throwable = e.getCause();
            if (null != throwable) {
                if (throwable.equals(SocketTimeoutException.class)) {
                    result = StringConstant.errorstate4;
                }
            }

            String msg = e.getMessage();
            if (!BooleanUtils.isEmpty(msg) && msg.contains("timeout")) {
                result = StringConstant.errorstate4;
            }

        }

        return result;
    }

}

 

 

P层 Presenter

 

1.基础Presenter

public class BasePresenter {

    protected RxAndroidOkhttp mRxAndroidOkhttp=null;//RxAndroidOkhttp对象
    protected Observable mObservable=null;//get post 方式请求的Observable对象

    public BasePresenter(){
        mRxAndroidOkhttp=RxAndroidOkhttp.getInstance();
    }

}

 

2.登录Presenter

public class LoginPresenter extends BasePresenter{

    /**
     * 构造方法
     * */

    public LoginPresenter(){
        super();
    }

    /**
     * 响应回调
     * */

    private OkHttpResponseInterface mOkHttpResponseInterface=null;
    public void setOnOkHttpResponseListener(OkHttpResponseInterface okHttpResponseInterface){
        mOkHttpResponseInterface=okHttpResponseInterface;
    }

    /**
     * 请求数据
     * */

    public void requestService(final String type,final String posturl,final Map params){
        if(null!=mRxAndroidOkhttp){
            //observable定义被观察者
            mObservable=mRxAndroidOkhttp.post(posturl,params);
            if(null!=mObservable){
                //定义观察者
                Subscriber mSubscriber=new Subscriber(){
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        if(mOkHttpResponseInterface!=null) {
                            mOkHttpResponseInterface.onOkHttpError(type,e);
                        }
                    }

                    @Override
                    public void onNext(String s) {
                        if(mOkHttpResponseInterface!=null) {
                            mOkHttpResponseInterface.onOkHttpNext(type,s);
                        }
                    }
                };

                /**
                 * 订阅者关联被观察者
                 * Schedulers.io()说明是输入输出的计划任务
                 * AndroidSchedulers.mainThread()说明订阅者是中ui主线程中执行
                 * */

                mObservable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(mSubscriber);
            }
        }
    }

}

 

接口

/**
 * @param :OkHttpResponse接口
 * @author :wjn
 * */

public interface OkHttpResponseInterface {

    void onOkHttpError(String type,Throwable e);

    void onOkHttpNext(String type,String s);

}

 

 

 

V层  View

 

1.基础Activity

public abstract class BaseActivity extends AppCompatActivity {

    /**
     * onCreate 方法
     * */

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());
        setStatusBarMode();
        initView();
        initPresenter();
    }

    /**
     * 获取布局id
     */

    public abstract int getLayoutId();

    /**
     * 初始化视图
     */

    protected abstract void initView();

    /**
     * 初始化视图
     */

    protected abstract void initPresenter();

    /**
     * 初始化状态栏
     * 文字、图标是否为黑色 (false为默认的白色)
     */

    protected abstract boolean isTextDark();

    /**
     * 初始化状态栏
     * 本地颜色还是获取的rgb颜色值
     */

    protected abstract boolean islocalcolor();

    /**
     * 初始化状态栏
     * 状态栏颜色
     */

    protected abstract int colorId();

    /**
     * 初始化状态栏
     */

    protected void setStatusBarMode(){
        //根据状态栏颜色来决定 状态栏背景 用黑色还是白色 true:是否修改状态栏字体颜色
        StatusBarUtil.setStatusBarMode(this, isTextDark(), islocalcolor(), colorId());
    }

}

 

 

2.登录Activity

public class MVP_LoginActivity extends BaseActivity implements OkHttpResponseInterface, View.OnClickListener {

    private TextView textView1;
    private TextView textView11;
    private TextView resultTextView;
    private LoginPresenter loginPresenter=null;

    /**
     * 获取布局
     * */

    @Override
    public int getLayoutId() {
        return R.layout.activity_login;
    }

    /**
     * 初始化状态栏
     * 文字、图标是否为黑色 (false为默认的白色)
     */

    @Override
    protected boolean isTextDark() {
        return true;
    }

    /**
     * 初始化状态栏
     * 本地颜色还是获取的rgb颜色值
     */

    @Override
    protected boolean islocalcolor() {
        return false;
    }

    /**
     * 初始化状态栏
     * 状态栏颜色
     */

    @Override
    protected int colorId() {
        return R.color.baise;
    }

    /**
     * 初始化View方法
     * */

    @Override
    protected void initView() {
        textView1=findViewById(R.id.activity_login_textview1);
        textView11=findViewById(R.id.activity_login_textview11);
        resultTextView=findViewById(R.id.activity_login_textview2);
        textView1.setOnClickListener(this);
        textView11.setOnClickListener(this);
    }

    /**
     * 初始化Presenter
     * */

    @Override
    protected void initPresenter() {
        loginPresenter=new LoginPresenter();
        loginPresenter.setOnOkHttpResponseListener(this);
    }

    /**
     * 各种点击事件的方法
     * */

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.activity_login_textview1://登录 Post
                loginMethod();
                break;
            case R.id.activity_login_textview11://翻译 Post
                fanyiMethod();
                break;
            default:
                break;
        }
    }

    /**
     * 自定义 OkHttp onError方法
     * */

    @Override
    public void onOkHttpError(String type, Throwable e) {
        resultTextView.setText(e.getMessage());
    }

    /**
     * 自定义 OkHttp onNext方法
     * */

    @Override
    public void onOkHttpNext(String type, String s) {
        if("Login".equals(type)){
            resultTextView.setText("登录结果显示:\n\n"+s);
        }else if("fanyi".equals(type)){
            resultTextView.setText("翻译结果显示:\n\n"+s);
        }
    }

    /**
     * 登录方法
     * */

    private void loginMethod(){
        resultTextView.setText("登录数据加载中...");
        Map params = new HashMap<>();
        params.put("userName", "");//用户名
        params.put("password", "");//密码
        params.put("JPID", "");//JPID 手机型号
        params.put("token", "");//登录token
        loginPresenter.requestService("Login",StringConstant.loginposturl,params);
    }

    /**
     * 翻译方法
     * */

    private void fanyiMethod(){
        resultTextView.setText("翻译数据加载中...");
        Map params = new HashMap<>();
        params.put("keyfrom", "");
        params.put("key", "");
        params.put("type", "");
        params.put("doctype", "");
        params.put("version", "");
        params.put("q", "");
        loginPresenter.requestService("fanyi",StringConstant.fanyiposturl,params);
    }

}

 

 

3.登录Activity布局




    

    

        

            

            


            


        

    

 

你可能感兴趣的:(Android,网络库)