带你封装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);
    }
}
复制代码


相关文章
|
2月前
|
前端开发 测试技术 数据处理
Kotlin教程笔记 - MVP与MVVM架构设计的对比
Kotlin教程笔记 - MVP与MVVM架构设计的对比
83 4
|
2月前
|
前端开发 JavaScript 测试技术
Kotlin教程笔记 - 适合构建中大型项目的架构模式全面对比
Kotlin教程笔记 - 适合构建中大型项目的架构模式全面对比
40 3
|
2月前
|
存储 前端开发 Java
Kotlin教程笔记 - MVVM架构怎样避免内存泄漏
Kotlin教程笔记 - MVVM架构怎样避免内存泄漏
34 2
|
2月前
|
XML 前端开发 Android开发
Kotlin教程笔记(80) - MVVM架构设计
Kotlin教程笔记(80) - MVVM架构设计
|
2月前
|
XML 前端开发 Android开发
Kotlin教程笔记(80) - MVVM架构设计
Kotlin教程笔记(80) - MVVM架构设计
|
3月前
|
XML 前端开发 Android开发
Kotlin教程笔记(80) - MVVM架构设计
Kotlin教程笔记(80) - MVVM架构设计
36 1
|
2月前
|
前端开发 Java 测试技术
android MVP契约类架构模式与MVVM架构模式,哪种架构模式更好?
android MVP契约类架构模式与MVVM架构模式,哪种架构模式更好?
93 0
|
3月前
|
存储 前端开发 Java
Kotlin教程笔记 - MVVM架构怎样避免内存泄漏
Kotlin教程笔记 - MVVM架构怎样避免内存泄漏
|
1月前
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
|
2月前
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
63 3

热门文章

最新文章