IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 二次封装三方框架 -> 正文阅读

[移动开发]Android 二次封装三方框架

一、背景

开发当中,在请求网络的时候,大家或多或少都会使用一些第三方框架,Android-Async-Http、 Volley、XUtils、Okhttp、Retrofit 等。这些框架减少了我们的很多工作量,同时也对侵入了我们的项目。

大家回顾一下手头上的项目代码,是不是或多或少存在这样那样的历史遗留问题,第三方框架调用混乱,没有封装,或者封装不彻底。如果要替换框架,很有可能要对项目大动干戈。

二、封装的必要性

  • 随着需求的变更或者时间的迁移,某些框架可能已经不能满足我们的需求,我们需要使用新的框架来代替
  • 对第三方框架进行封装,是为了达到对模块项目的控制,已最小的代价替换框架,达到对项目的控制

三、封装网络库示例

我们先来看一下 okHttp 的使用:

OkHttpClient.Builder mBuilder= new OkHttpClient.Builder()
					.connectTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS)
			        .readTimeout(30, TimeUnit.SECONDS)
			        .addInterceptor(new LoggingInterceptor())
			        .cache(new Cache(mContext.getExternalFilesDir("okhttp"),cacheSize));
        
client=mBuilder.build();

Request.Builder builder = new Request.Builder().url(url).tag(option.mTag);
builder = configHeaders(builder,option);

Request build = builder.build();

client.newCall(build).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        handleError(e, iResponseListener);
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        handleResult(response, iResponseListener);
    }
});

如果不进行封装,okHttp 请求网络大概是这样的,想一下,如果我们在项目中都这样使用,要替换框架,那花费的工作量要多大。

不过这种方法,在项目中大多数人不会这样使用,至少都会封装成为一个工具类。封装完成之后如下:

public static void  doGet(Context context,String url, Map<String, String> paramsMap, NetworkOption networkOption,final IResponseListener iResponseListener){
      OkHttpClient.Builder mBuilder= new OkHttpClient.Builder()
      		  .connectTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS)
              .readTimeout(30, TimeUnit.SECONDS)
              .addInterceptor(new LoggingInterceptor())
              .cache(new Cache(context.getExternalFilesDir("okhttp"),cacheSize));
      OkHttpClient cilent = mBuilder.build();

      Request.Builder builder = new Request.Builder().url(url);


      Request build = builder.build();

      cilent.newCall(build).enqueue(new Callback() {
          @Override
          public void onFailure(Call call, IOException e) {
              handleError(e, iResponseListener);
          }

          @Override
          public void onResponse(Call call, Response response) throws IOException {
              handleResult(response, iResponseListener);
          }
      });
  }

public static void doPost(Context context,String url, Map<String, String> paramsMap, NetworkOption networkOption, final IResponseListener iResponseListener) {
     OkHttpClient.Builder mBuilder= new OkHttpClient.Builder()
     		.connectTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS)
             .readTimeout(30, TimeUnit.SECONDS)
             .addInterceptor(new LoggingInterceptor())
             .cache(new Cache(context.getExternalFilesDir("okhttp"),cacheSize));
     OkHttpClient cilent = mBuilder.build();
     url= NetUtils.checkUrl(url);
     final NetworkOption option=NetUtils.checkNetworkOption(networkOption,url);
     FormBody.Builder builder = new FormBody.Builder();
     FormBody formBody = builder.build();

     Request.Builder requestBuilder = new Request.Builder().url(url).post(formBody).tag(option.mTag);
     Request request = requestBuilder.build();
     cilent.newCall(request).enqueue(new Callback() {
         @Override
         public void onFailure(Call call, IOException e) {
             handleError(e,iResponseListener);
         }

         @Override
         public void onResponse(Call call, Response response) throws IOException {
             handleResult(response,iResponseListener);
         }
     });
 }

这种封装成工具类的比完全没有封装的好了很多,但是还是存在一定的问题的。封装成工具类的话,别人完全有权限访问你这个工具类,他可以随时修改你工具类里面的实现,这给维护带来了一定的成本。那有没有更好的方法呢?
大多数人都会想到的是封装统一网络接口,没错,确实是这样。于是,经过一番思考以后,我们可能写出以下的代码。

void doGet(Context context,String url, final Map<String, String> paramsMap, final IResponseListener iResponseListener);

如果我们需要动态配置请求头呢,请求 TAG 呢,这时候你会怎么写,继续增加参数吗?

void doGet(Context context,String url, final Map<String, String> paramsMap,final Map<String, String> headMap, String tag,final IResponseListener iResponseListener);

那以后如果要配置缓存路径呢,配置请求超时时间,读取超时时间呢,直接在方法中增加相应的参数?

这样的做法是不太明智的,会导致接口越来越臃肿。

既然这样,那有没有办法解决呢?

首先,我们先回想一下,网络请求那些参数是必要的,那些是非必要的,即可有可无的。

必要选项

  • url,请求网址
  • paramsMap ,请求参数
  • iResponseListener 请求结果的回调

非必要选项

  • context 通常是用来配置配置一些缓存等一些信息
  • headMap 请求头
  • tag 请求 TAG,用来区分或者取消网络请求
  • connectTimeout 连接超时时间
  • readTimeout 读取超时时间
  • writeTimeout 写入超时时间

了解完必要参数和非必要参数之后,我们的接口要怎样提取呢?

不知道大家有没有注意到 okHttpClient 的构建,他将所有的网络配置都提取封装在 OkHttpClient,Request 中,在请求网络的时候减少了相应的参数,简洁灵活。

OkHttpClient.Builder mBuilder= new OkHttpClient.Builder()
		.connectTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .addInterceptor(new LoggingInterceptor())
        .cache(new Cache(context.getExternalFilesDir("okhttp"),cacheSize));
OkHttpClient cilent = mBuilder.build();

Request.Builder builder = new Request.Builder().url(url);
client.newCall(builder.build()).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        handleError(e, iResponseListener);
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        handleResult(response, iResponseListener);
    }
});

看了 OKhttp 的代码,我们也可以依样画葫芦,我们可以将非必要参数封装在一个实体类 NetworkOption 当中,必要的参数作为方法参数,这样接口变成以下的形式

void doGet(String url, final Map<String, String> paramsMap, final IResponseListener iResponseListener);

void doGet(String url, final Map<String, String> paramsMap, NetworkOption networkOption, final IResponseListener iResponseListener);

对比直接在方法中增加相应的参数,是不是简洁很多。

接着,我们一起来看一下 NetworkOption 的属性。基本上,只要 okhttp 可以配置的,我们都可以往里面配置。这里列举了一些常用的字段 ,baseUrl,请求标志 tag,请求头 mHeaders。-connectTimeout 连接超时时间,readTimeout 读取超时时间,writeTimeout 写入超时时间就不一一列举了。

public class NetworkOption {

    /**
     * 网络请求的 TAG
     */
    public String mBaseUrl;
    public String mTag;
    public Map<String,String> mHeaders;

    public NetworkOption(String tag) {
        this.mTag = tag;
    }

    public static final  class Builder{
        public String tag;
        public Map<String,String> mHeaders;
        public String mBaseUrl;

        public Builder setTag(String tag){
            this.tag=tag;
            return this;
        }

        public Builder setHeaders(Map<String,String> headers){
            mHeaders=headers;
            return this;

        }

        public Builder setBaseUrl(String baseUrl) {
            mBaseUrl = baseUrl;
            return this;
        }

        public NetworkOption build(){
            NetworkOption networkOption = new NetworkOption(tag);
            networkOption.mHeaders=mHeaders;
            networkOption.mBaseUrl=mBaseUrl;
            return networkOption;
        }
    }
}

最后的封装实现

public interface NetRequest {

     void init(Context context);

     void doGet(String url, final Map<String, String> paramsMap, final IResponseListener iResponseListener);

     void doGet(String url, final Map<String, String> paramsMap, NetworkOption networkOption, final IResponseListener iResponseListener);

     void doPost(String url, final Map<String, String> paramsMap, final IResponseListener iResponseListener);

     void doPost(String url, final Map<String, String> paramsMap, NetworkOption networkOption,final IResponseListener iResponseListener);

     void cancel(Object tag);
}
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-05 17:27:58  更:2021-08-05 17:30:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 9:51:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码