全新MVP,你get到我的点了吗?(含java和kotlin代码)

写在开头

PS:最近也在一直在学习kotlin,所以在写完java后也手撸了一遍kotlin,其中包含自己在kotlin学习中的一些笔记什么的。后续有新想法也会一直更新什么的。下一步打算加入本地Mock json数据的功能。

不多说,本文围绕一张图展开,请查阅,欢迎共同讨论,叨扰了。如果你还有什么需求或者什么想法,可一起完善此demo一起进步哦!!!

这里写图片描述

github:https://github.com/loveAndroidAndroid/MvpProject ,欢迎共同学习!可下载java和kotlin版本。
优快云:https://download.youkuaiyun.com/download/say_from_wen/10671387 (java)
https://download.youkuaiyun.com/download/say_from_wen/10691277 (kotlin版本)

让我们从library到mouble,让我们谈谈我理解的项目的Project架构。本文章全部就java版本来谈,如果对于kotlin版本的探讨,可留言或者QQ认基友807315559 哈哈

##lib-network封装浅谈

如果是你封装这个的话,你想到的会是什么?一个好的网络底层封装库应该具备哪些功能?

首先:

  1. 这个网络库不应该和业务有任何的联系,只提供对外设置参数的方法。
  2. 无论后端返回数据格式是否变化(比如成功的时候是对象,失败会返回数组格式),不会报错解析错误。
  3. 自定义各种异常的友好提示
  4. 支持https设置
  5. 支持本地域名验证

下面我们看一下我的想法:

1.关于第一个问题:主要代码在RetrofitUtil工具类中,所有设置所需的参数都由外部设置进来,提供必要的可扩展性:

 public void init(String baseURL, long readTime, long writeTime, long connectTime, SocketFactory socketFactory, HostnameVerifier hostnameVerifier, Interceptor... interceptor) {
        if (gson == null) {
            gson = new GsonBuilder()
                    .enableComplexMapKeySerialization() //支持Map的key为复杂对象的形式
                    .create();
        }
        retrofit = new Retrofit.Builder()
                .baseUrl(baseURL)
                .client(genericClient(readTime, writeTime, connectTime, socketFactory, hostnameVerifier, interceptor))
                //2.自定义ConverterFactory处理异常情况
                .addConverterFactory(JsonArrayConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }

    public OkHttpClient genericClient(long readTime, long writeTime, long connectTime, SocketFactory socketFactory, HostnameVerifier hostnameVerifier, Interceptor... interceptors) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .readTimeout(readTime, TimeUnit.SECONDS)
                .writeTimeout(writeTime, TimeUnit.SECONDS)
                .connectTimeout(connectTime, TimeUnit.SECONDS);
        //      可以添加进来https认证
//              .socketFactory(socketFactory)
//              .hostnameVerifier(hostnameVerifier);
        if (interceptors != null && interceptors.length > 0) {
            for (int i = 0; i < interceptors.length; i++) {
                builder.addInterceptor(interceptors[i]);
            }
        }
        return builder.build();
    }

2.不知道你的后台是不是PHP,不知道你有没有遇到过后台数据格式返回在正确的时候是个对象object,出错的时候是个数组array。然后给你报错解析异常,后来经过了解,PHP都是以Array取值,给我们返回的object也是他们强转的,我总不能要求人家每次或者每个错误都给我处理吧。无奈之只能自己搞了。

自定义Converter能解决我们的烦恼:主要为以下代码,核心思想其实利用Gosn的分段解析的一个思想。

 @Override
    public T convert(ResponseBody value) throws IOException {
        String response = value.string();
        try {
            //ResultResponse 只解析status字段
            ResultResponse resultResponse = gson.fromJson(response, ResultResponse.class);
            if (Integer.parseInt(resultResponse.getStatus()) == 200) {
                //result==200表示成功返回,继续用本来的Model类解析
                return gson.fromJson(response, type);
            } else {
                //ErrResponse 将msg解析为异常消息文本
                ErrResponse errResponse = gson.fromJson(response, ErrResponse.class);
                throw new ResultException(resultResponse.getStatus(), errResponse.getMsg());
            }
        } finally {
        }
    }

3.关于网络请求,出错的情况千遍万变,我们总要自定义一些自己的友好提示,我们如何拦截并设置呢?因为我用的事RxJava2.x,所以此时通过自定义DisposableSubscriber实现,关于友好提示,当然是由你的产品来定,对外提供成功和失败的方法就行了。建议代码如下:

/**
 * Created by wen on 2018/5/14.
 * 适配器模式  去除不必要的接口方法
 */
public abstract class ApiSubscriberCallBack<T> extends DisposableSubscriber<T> {

    @Override
    public void onNext(T t) {
        onSuccess(t);
    }

    @Override
    public void onError(Throwable e) {
        e.printStackTrace();

        //在这里做全局的错误处理
        if (e instanceof HttpException||
                e instanceof ConnectException ||
                e instanceof SocketTimeoutException ||
                e instanceof TimeoutException ||
                e instanceof UnknownHostException) {
            //网络错误
            onFailure(new Throwable("网络不好哦亲,请确认网络重新连接"));
        } else if (e instanceof ResultException) {
            //todo 自定义的ResultException  此处结合业务进行处理
            onFailure(e);
        } else {
            //其他错误
            onFailure(new Throwable("未知错误,地球即将爆炸,请赶紧跑路"));
        }
    }

    @Override
    public void onComplete() {
    }

    public abstract void onSuccess(T t);

    public abstract void onFailure(Throwable t);
}

case 4:

case 5:关于Https设置和域名设置,暂不提供,可google一下就好,有问题可留言讨论。

##lib-image封装浅谈

图片封装的话,我感觉我们还是考虑封装一些通过的效果,比如圆形圆角等,其他的可以通过提供方法设置进去比较好。当然,不要和业务有关联。

图片库功能:

  1. 自定义ResponseBody实现对图片加载进度的监听。
  2. 自定义BitmapTransformation实现各种通用效果
  3. 提供初始化工具类
  4. 提供Glide缓存清理工具类

1.自定义ResponseBody(Glide4.x)

如果我们不使用Glide的话,我们首先得自定义RegistersComponents并重写RegistersComponents方法来实现对网络请求的监听,替换Glide的默认加载、解码和*编码逻辑。。Glide的话,在4.x以后提供了AppGlideModule的封装类,我们继承它实现registerComponents就好了,代码如下:

@GlideModule
public class ProgressAppGlideModule extends AppGlideModule {
    @Override
    public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
        super.registerComponents(context, glide, registry);
        registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(ProgressManager.getOkHttpClient()));
    }
}

然后,我们需要将我们自定义的ResponseBody设置给OkHttpClient,并在ResponseBody的source方法中的ForwardingSource内部类中的read方法返回我们需要的进度,主要代码如下:

	 private Source source(Source source) {
        return new ForwardingSource(source) {
            long totalBytesRead;
            long lastTotalBytesRead;

            @Override
            public long read(@NonNull Buffer sink, long byteCount) throws IOException {
                long bytesRead = super.read(sink, byteCount);
                totalBytesRead += (bytesRead == -1) ? 0 : bytesRead;

                if (internalProgressListener != null && lastTotalBytesRead != totalBytesRead) {
                    lastTotalBytesRead = totalBytesRead;
                    mainThreadHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            internalProgressListener.onProgress(url, totalBytesRead, contentLength());
                        }
                    });
                   }
                return bytesRead;
            }
        };
    }

2.通过BitmapTransformation实现各种各样的图片效果

我们还是主要通过Transformation的transform方法中来对bitmap进行处理来返回我们最终想要的效果,例如我们实现一个圆形效果:(代码会有详细的注释)

	@Override
    protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
        //得到图片最小边
        int size = Math.min(toTransform.getWidth(), toTransform.getHeight());
        //计算图片起点
        int x = (toTransform.getWidth() - size) / 2;
        int y = (toTransform.getHeight() - size) / 2;
        //创建新的bitmaop
        Bitmap square = Bitmap.createBitmap(toTransform, x, y, size, size);
        //得到glide中BitmapPool的bitmap位图对象
        Bitmap circle = pool.get(size, size, Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(circle);
        Paint paint = new Paint();
        //设置TileMode的样式 CLAMP 拉伸 REPEAT 重复  MIRROR 镜像
        paint.setShader(new BitmapShader(square, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float r = size / 2f;
        //画圆
        canvas.drawCircle(r, r, r, paint);
        return circle;
    }

3.初始化工具类

4.缓存处理工具类

其实没啥好写的,就是封装一些方法共外界调用,具体的话欢迎下载代码查看。

##lib-core封装浅谈

说到这个模块,就涉及到组件化的一些概念了。lib-core的概念主要就是为上层mouble提供公共服务的一个隔离层,起到承上启下的作用。比如说网络与图片,他肯定是所有mouble一定要使用的两个功能。所以我把它封装进了lib-core中,在其中采用代理模式隔离底层库和上层mouble,更大程度的实现了解耦。下图是他的构造。

这里写图片描述

base:主要是MVP的一层封装,采用泛型和继承的思想进行了封装,包括loading的显示隐藏逻辑,网络请求的控制,ButterKnife的的注册与反注册等等
bean:就会一个总的data类。
config:采用建造者模式给mouble提供网络库和图片库的全局初始化。
imagehelper:GlideManger提供的图片加载的方法,mouble传入固定的参数来加载想要的图片。
nethelper:这个文件夹下写了三个interceptor,可以打印okhttp的日志和在header里添加和获取参数。(如果您项目没在项目中在header中添加固定参数,也可以自定义interceptor实现参数的添加,项目在使用,后续会在demo更新中添加)
view:自定义的loading显示,不在多说。

PS:关于此部分代码,在这里写不列出,如果您正好有需要,欢迎下载共同学习。

##APPMouble:
主要是对封装的库的一些使用,没啥好看的界面,争取后面能够补充到。

#写在最后

适合自己的架构才是最好的架构,希望和大家一起学习进步,也希望大家不令赐教。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值