开发者社区> Yj家的孺子牛> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

带你封装MVP架构(上)|青训营笔记(二)

简介: 我们做一个 MVP 架构的封装,主要其相对于MVC更加解耦,能让开发人员在编写代码的时候更加高效和舒服。
+关注继续查看

MyUtil

该工具类获得了一个全局的 Context ,以及根据此context,创建了开启加载动画以及关闭加载动画的方法

public class MyUtil {
    /**
     * 全局context
     */
    private static Application mApplicationContext;
    private static RxDialogLoading rxDialogLoading;
    /**
     * @param app 初始化全局context
     */
    public static void initialize(Application app) {
        mApplicationContext = app;
    }
    /**
     * 获得全局context
     *
     * @return 当前的全局context
     */
    public static Application getApplication() {
        return mApplicationContext;
    }
    /**
     * 关闭键盘
     */
    public static void closeSoftKeyboard() {
        InputMethodManager inputManger = (InputMethodManager) ActivityUtil.getCurrentActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputManger != null) {
            inputManger.hideSoftInputFromWindow(ActivityUtil.getCurrentActivity().getWindow().getDecorView().getWindowToken(), 0);
        }
    }
    public static String getString(int id) {
        return getApplication().getResources().getString(id);
    }
    /**
     * 展示dialog
     *
     * @param context 传入当前Acitivity
     */
    public static void showLoading(Context context){
        if (rxDialogLoading == null){
            rxDialogLoading = new RxDialogLoading(context);
            rxDialogLoading.setCanceledOnTouchOutside(false);
        }
        rxDialogLoading.show();
    }
    /**
     * 成功隐藏dialog,显示成功
     */
    public static void dismissSuccessLoading(){
        rxDialogLoading.cancel(RxDialogLoading.RxCancelType.success,getString(R.string.load_success));
    }
    /**
     * 失败隐藏dialog,显示失败
     */
    public static void dismissFailedLoading(){
        rxDialogLoading.cancel(RxDialogLoading.RxCancelType.error,getString(R.string.load_error));
    }
}
复制代码

Retrofit + Rxjava 打造优雅网络请求方式

由于该模块代码繁多,文章不会描述每一个类,完整代码请查阅http

其中的 cookie 包是用于做登录状态持久化,但是本demo中未用到

gson 包是做了一个转换器,对网络数据的请求报文和响应报文做了一次数据筛查

API 类是定义了所有的网络请求方法

RetrofitService 类是对该网络模块的集成的方法,是 Retrofit 的核心方法

BaseResponseBodyConverter

该方法是继承了类型为响应报文的 Retrofit 转换器类,可以对对响应报文做数据筛查。我们可以筛查出响应的报文的错误码或者错误描述进行自动的异常处理。

例如返回的错误码描述为当前登录状态过期,那么我们可以取消登录状态,程序自动跳转到登录页面中。

亦或是错误码为非正常状态下,自动抛出自定义的异常,然后App对该异常做 Toast 描述之类的

public class BaseResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final TypeAdapter<T> adapter;
    BaseResponseBodyConverter(TypeAdapter<T> adapter) {
        this.adapter = adapter;
    }
    @Override
    public T convert(ResponseBody value) throws IOException {
        String jsonString = value.string();
        try{
            JSONObject object = new JSONObject(jsonString);
            int code = object.getInt(MyUtil.getString(R.string.code));
            String data ;
            if (code == 1) return adapter.fromJson(jsonString);
            else  data = object.getString(MyUtil.getString(R.string.msg));
            throw new BaseException(code, data);
        }catch (JSONException ex){
            ex.printStackTrace();
            try {
                JSONObject object = new JSONObject(jsonString);
                int error_code = object.getJSONObject("data").getInt(MyUtil.getString(R.string.error_code));
                if (0 != error_code ) {
                    String data;
                    data = object.getJSONObject("data").getString(MyUtil.getString(R.string.error_msg));
                    //异常处理
                    throw new BaseException(error_code, data);
                }
                //正确返回整个json
                return adapter.fromJson(jsonString);
            } catch (JSONException e) {
                e.printStackTrace();
                //数据解析异常即json格式有变动
                throw new BaseException(MyUtil.getString(R.string.PARSE_ERROR_MSG));
            }
        }finally {
            value.close();
        }
    }
}
复制代码

需要注意的是,我们需要针对不同格式的响应报文,定制不同的筛查策略和处理逻辑

MoreBaseUrlInterceptor

自定义一个过滤器,在该过滤器中,我们可以对请求的做一些自动的更改

例如下例,我们可以在检测到请求头中带 urlName 字段的时候,去做一个对应的 BaseUrl 的更新;我们也还可以在这里做一些譬如key这些字段的添加等等

public class MoreBaseUrlInterceptor implements Interceptor {
    private final HashMap<String,String> keyUrl;
    public MoreBaseUrlInterceptor(HashMap<String, String> keyUrl) {
        this.keyUrl = keyUrl;
    }
    @Override
    public Response intercept(Chain chain) throws IOException {
        //获取原始的originalRequest
        Request originalRequest = chain.request();
        //获取老的url
        HttpUrl oldUrl = originalRequest.url();
        //获取originalRequest的创建者builder
        Request.Builder builder = originalRequest.newBuilder();
        //获取头信息的集合如:base,geo
        List<String> urlNameList = originalRequest.headers("urlName");
        if (urlNameList.size() > 0) {
            //删除原有配置中的值,就是namesAndValues集合里的值
            builder.removeHeader("urlName");
            //获取头信息中配置的value,如:m或者mock
            String urlName = urlNameList.get(0);
            HttpUrl baseURL;
            //根据头信息中配置的value,来匹配新的base_url地址
            baseURL = HttpUrl.parse(Objects.requireNonNull(keyUrl.get(urlName)));
            //重建新的HttpUrl,需要重新设置的url部分
            HttpUrl newHttpUrl = oldUrl.newBuilder()
                    .scheme(baseURL.scheme())//http协议如:http或者https
                    .host(baseURL.host())//主机地址
                    .encodedPath(baseURL.encodedPath() +
                            oldUrl.encodedPath().substring(1))//构建路径,为适配MOCK中给出的BaseURL带有Path路径的情况
                    .port(baseURL.port())//端口
                    .build();
            //获取处理后的新newRequest
            Request newRequest = builder.url(newHttpUrl).build();
            return  chain.proceed(newRequest);
        }else{
            Request reOriginalRequest = builder.url(oldUrl).build();
            return chain.proceed(reOriginalRequest);
        }
    }
}
复制代码

RetrofitService

该类是 Retrofit 服务类,对外提供一个服务的单例,然后添加好前面编写的转换器以及过滤器等信息。这样子供外部统一调用这个 Retrofit 单例即可。

public class RetrofitService {
    private volatile static RetrofitService apiRetrofit;
    private API.SZApi apiServer;
    /**
     * 单例调用
     *
     * @return RetrofitService
     */
    public static RetrofitService getInstance() {
        if (apiRetrofit == null) {
            synchronized (Object.class) {
                if (apiRetrofit == null) {
                    apiRetrofit = new RetrofitService();
                }
            }
        }
        return apiRetrofit;
    }
    /**
     * 获取api对象
     *
     * @return api对象
     */
    public API.SZApi getApiService() {
        return apiServer;
    }
    /**
     * 初始化retrofit
     */
    private RetrofitService() {
        //配置okHttp并设置时间、日志信息和cookies
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new MoreBaseUrlInterceptor(API.getKeyUrl()))
                .addInterceptor(httpLoggingInterceptor)
                //设置超时时间
                .connectTimeout(15, TimeUnit.SECONDS)
                //设置Cookie持久化
//                .cookieJar(new CookiesManager(MyUtil.getApplication()))
                .build();
        //关联okHttp并加上rxJava和Gson的配置和baseUrl
        Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(BaseConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(API.BASE_URL)
                .build();
        apiServer = retrofit.create(API.SZApi.class);
    }
}
复制代码


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
iOS开发 - 抛开表面看本质之iOS常用架构(MVC,MVP,MVVM)
iOS开发 - 抛开表面看本质之iOS常用架构(MVC,MVP,MVVM)
0 0
Kotlin学历之Android MVP架构实战
Kotlin学历之Android MVP架构实战
0 0
一文带你玩转安卓Kotlin+Retrofit+RxJava+MVP架构(附Demo)
一文带你玩转安卓Kotlin+Retrofit+RxJava+MVP架构
0 0
带你封装MVP架构(上)|青训营笔记(一)
我们做一个 MVP 架构的封装,主要其相对于MVC更加解耦,能让开发人员在编写代码的时候更加高效和舒服。
0 0
带你封装MVP架构(下)|青训营笔记(二)
在 Base 类中,我们需要做的就是把每个 Activity 或者 Fragment 等这些组件,或者对应的 MVP 层会用到的基本操作以及联系都编写好。
0 0
Jetpack 系列(5)—— Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
Jetpack 系列(5)—— Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
0 0
Jetpack Compose 架构如何选? MVP, MVVM, MVI
虽然 Compose 1.0 即将发布,但真正要在项目中落地还少不了一套合理的应用架构,面对MVP、MVVM、MVI等架构应该如何选择呢
0 0
Android 架构MVC MVP MVVM+实例(下)
实例 MVC实例 代码结构 1.在layout创建一个布局文件 2.实体类(User) 3.MVCLoginActivity MVP实例 代码结构 1.Model层 2.Presenter层 3.View层 MVVM实例 1.Model层 2.ViewModel层 3.View层 实例传送门
0 0
Android 架构MVC MVP MVVM+实例(上)
前言 MVC是什么? Android中的MVC含义 工作原理 MVC的缺点 MVP是什么 Android中的MVP含义 工作原理 MVP的优点 MVP的缺点 MVVM是什么 Android中的MVVM含义 工作原理 MVVM的优点 MVVM的缺点 MVP和MVC的最大区别 如何选取框架
0 0
【权限设计系列】「认证授权专题」微服务架构的登陆认证问题
【权限设计系列】「认证授权专题」微服务架构的登陆认证问题
0 0
+关注
Yj家的孺子牛
广东工业大学数智工作室 Android开发工程师
文章
问答
文章排行榜
最热
最新
相关电子书
更多
云原生架构白皮书2022年新版
立即下载
技术揭秘:RocketMQ 5.0 云原生架构升级之路
立即下载
基于英特尔®架构的阿里云服务网格ASM技术加速应用服务加密通
立即下载