0
点赞
收藏
分享

微信扫一扫

Android 二次封装网络加载框架,oppoAndroid面试

草原小黄河 2022-03-11 阅读 199

.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 呢,这时候你会怎么写,继续增加参数吗?

这时候接口可能如下:

public interface NetRequest{

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;

}

}

}

同时,考虑到 NetworkOption 对象的配置会比较复杂,这里我们采用了建造者模式来构建。有兴趣的话,可以参考我的这一篇博客。建造者模式(Builder)及其应用

建造者模式的优点

  • 封装性很好,将产品本身与产品的创建过程解耦,对外屏蔽了对象的构建过程

  • 扩展性强,如果有新的需求,只需要增加新的具体建造者,无须修改原有类库的代码

最后的封装实现


NetRequest 接口的封装

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);

}

可以看到,我们主要有几个方法

  • init 方法,主要用来配置一些初始化参数

  • doGet 有两个方法,其中一个方法是另外一个方法的重载,这样设计的目的是为了减少调用方法的时候减少方法参数的传递

  • doPost 跟 doGet 方法一样,就不说了

  • cancel 主要是用来取消网络请求的。在项目当中,在 Activity 或者 Fragment 销毁的时候,最好取消网络请求,不然可能导致内存泄露或者异常,如空指针异常等。

OkHttpRequest 的实现

OkHttp 的配置是非常灵活的,这样我们主要看一下怎么配置请求头,请求参数,以及怎样取消网络请求。

public class OKHttpRequest implements NetRequest {

// ----- 省略若干方法,有兴趣的话上 github 查阅

@Override

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

doGet(url,paramsMap,null,iResponseListener);

}

@Override

public void doGet(String url, Map<String, String> paramsMap, NetworkOption networkOption,

final IResponseListener iResponseListener) {

url= NetUtils.checkUrl(url);

url=NetUtils.appendUrl(url,paramsMap);

final NetworkOption option=NetUtils.checkNetworkOption(networkOption,url);

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

builder=configHeaders(builder,option);

Request build = builder.build();

getCilent().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);

}

});

}

private Request.Builder configHeaders(Request.Builder builder, NetworkOption option) {

Map<String, String> headers = option.mHeaders;

if(headers==null || headers.size()==0){

return builder;

}

Set<Map.Entry<String, String>> entries = headers.entrySet();

for(Map.Entry<String, String> entry: entries){

String key = entry.getKey();

String value = entry.getValue();

// 添加请求头

builder.addHeader(key,value);

}

return builder;

}

@Override

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

doPost(url,paramsMap,null,iResponseListener);

}

private FormBody.Builder configPushParam(FormBody.Builder builder, Map<String, String> paramsMap) {

if(paramsMap!=null){

Set<Map.Entry<String, String>> entries = paramsMap.entrySet();

for(Map.Entry<String,String> entry:entries ){

String key = entry.getKey();

String value = entry.getValue();

builder.add(key,value);

最后

光有这些思路和搞懂单个知识的应用是还远远不够的,在Android开源框架设计思想中的知识点还是比较多的,想要搞懂还得学会整理和规划:我们常见的**Android热修复框架、插件化框架、组件化框架、图片加载框架、网络访问框架、RxJava响应式编程框架、IOC依赖注入框架、最近架构组件Jetpack等等Android第三方开源框架,**这些都是属于Android开源框架设计思想的。如下图所示:

image

这位阿里P8大佬针对以上知识点,熬夜整理出了一本长达1042页的完整版如何解读开源框架设计思想PDF文档,内容详细,把Android热修复框架、插件化框架、组件化框架、图片加载框架、网络访问框架、RxJava响应式编程框架、IOC依赖注入框架、最近架构组件Jetpack等等Android第三方开源框架这些知识点从源码分析到实战应用都讲的简单明了。

image

image

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

的简单明了。**

[外链图片转存中…(img-K5HYeUF0-1646382605035)]

[外链图片转存中…(img-RT4uhea7-1646382605035)]

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断!!!

举报

相关推荐

0 条评论