App 组件化/模块化之路——如何封装网络请求框架

简介: App 组件化/模块化之路——如何封装网络请求框架 在 App 开发中网络请求是每个开发者必备的开发库,也出现了许多优秀开源的网络请求库。例如 okhttp retrofit android-async-http 这些网络请求库很大程度上提高程序猿的编码效率。

App 组件化/模块化之路——如何封装网络请求框架

在 App 开发中网络请求是每个开发者必备的开发库,也出现了许多优秀开源的网络请求库。例如

这些网络请求库很大程度上提高程序猿的编码效率。但是随着业务的发展,App 变得越来越大,我们将这些网络请求库加入到项目中直接使用,对我们业务类的入侵是非常强的。如果要进行业务分离时,这些网络请求代码将是一个阻止我们进一步工作的绊脚石。对开发者来说是非常痛苦的。

因此我们构建的网络请求框架要可以解决以下问题:

  • 分离业务与网络请求代码
  • 网络库可以很容易的被替换
  • 网络库可以很方便的复用

所以在 App 组件化/模块化开发架构思路 一文中,我们把网络请求作为内核层的一个组件。

封装第三方网络请求接口

一般来说,目前绝大部分 App 的数据请求都是使用 HTTP 协议,而数据交换的协议使用 json 格式。因此可以封装一个通用的请求接口。(当然还有其他一些协议,例如微信的 mars ,但是封装的思路是一致的,本文为了简单说明,暂时使用通用网络请求框架,不排除以后会对 mars 的封装)

首先预览一下框架结构

request-architecture

IRequest

这个类封装了网络请求的通用接口,定义请求接口 doRequest() 、获取请求连接 getUrl() 、获取请求方法 getHttpMethod() 等。

public interface IRequest {
    enum HttpMethod {
        GET, POST, PUT, DELETE
    }
    //... 为了减少代码的篇幅,省略一些对本文说明不重要的片段,本文代码可以在
      //https://github.com/wecodexyz/Componentization 获取到
    void addParams(Map<String, String> params);

    String getUrl();

    Pair<Integer, String> doRequest();

    boolean isSupportCache();

    void addHeader(String key, String value);

    HttpMethod getHttpMethod();
  
    //... 为了减少代码的篇幅,省略一些对本文说明不重要的片段,本文代码可以在
      //https://github.com/wecodexyz/Componentization 获取到
}

 

Request

这个类是个抽象类,对 IRequest 的实现。目前是一个简单封装的实现。

RequestWrapper

这个类是一个泛型类,继承于 Request 并对第三方请求库的封装。例如本文就是对 okhttp 的封装,而泛型 T 对象就是请求得到的具体数据类型。如果要对其他请求库进行封装,就可以参考这个类的实现。

注意这个类封装是纯粹的网络请求,不应该包含业务类相关的代码。否则无解决上文提出的三个问题。

public abstract class RequestWrapper extends Request {

    //... 为了减少代码的篇幅,省略一些对本文说明不重要的片段,本文代码可以在
      //https://github.com/wecodexyz/Componentization 获取到

    @Override
    public Pair<Integer, String> doRequest() {
        Pair<Integer, String> result = new Pair<>(ERROR_NETWORK, "");
        okhttp3.Request request = null;

        if (getHttpMethod() == HttpMethod.POST) {
            request = requestBuilder().url(getUrl()).post(requestBody()).build();
        } else {
            request = requestBuilder().url(getUrlWithParams()).build();
        }
        try {
            Response response = mClient.newCall(request).execute();
            if (response.isSuccessful()) {
                result = new Pair<>(response.code(), response.body().string());
            } else {
                result = new Pair<>(response.code(), response.message());
            }
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
        }
        return result;
    }

    //... 为了减少代码的篇幅,省略一些对本文说明不重要的片段,本文代码可以在
      //https://github.com/wecodexyz/Componentization 获取到


}

 

关键的代码是在 doRequest() 方法中,该方法实现了网络请求的代码,返回一个 Pair<Integer,String>对象,该对象的 first 属性是一个请求 code ,用于标识网络请求码(即是网络请求返回的200,404,301等)。而 second 就是网络请求的数据。

BaseTextRequest

这个类就是网络请求框架提供给业务类使用的一个接口。本文一开始就提出来 json 作为交互数据请求的协议。那么此类的封装就有利于业务数据的访问。

public abstract class BaseTextRequest<T> extends RequestWrapper {

    public BaseTextRequest(Context context) {
        super(context);
    }

    public Flowable<T> request() {
        return Flowable.fromCallable(new Callable<Pair<Integer, String>>() {
            @Override
            public Pair<Integer, String> call() throws Exception {
                Pair<Integer, String> result = doRequest();
                return result;
            }
        }).flatMap(new Function<Pair<Integer, String>, Publisher<T>>() {
            @Override
            public Publisher<T> apply(@NonNull Pair<Integer, String> pair) throws Exception {
                if (isSuccessful(pair.first)) {
                    return Flowable.just(onRequestFinish(pair.second));
                }
                return Flowable.just(onRequestError(pair.first, pair.second));
            }
        });

    }

    @Override
    public boolean isSupportCache() {
        return true;
    }

    protected abstract T onRequestFinish(String result);

    protected abstract T onRequestError(int code, String message);
}

 

由于请求网络是耗时的操作,rxjava2 来实现网络请求异步操作。 request 是对 RequestWrapper.doRequest() 方法的封装,并得到一个 Flowable 对象。同时定义了 onRequestFinish()onRequestError() 两个方法。

这两个方法就是具体业务类要处理的逻辑。

SimpleTextRequest

假设有一个请求业务数据接口,返回数据是一个字符串。那么我们使用我们的框架就是这样来使用。本文例子是请求我们项目中的 README.md 的内容。用起来非常简单,只要继承于 BaseTextRequest,并实现 getUrl()onRequestFinish() onRequestError()getHttpMethod() 这几个方法。

注意严格来说这是一个业务类,所以是不应该放在 core 目录下的。

public class SimpleTextRequest extends BaseTextRequest<String> {

    public SimpleTextRequest(Context context, Map<String, String> params) {
        super(context);
        addParams(params);
    }

    @Override
    public String getUrl() {
        return "https://raw.githubusercontent.com/wecodexyz/Componentization/master/README.md";
    }

    @Override
    public HttpMethod getHttpMethod() {
        return HttpMethod.GET;
    }

    @Override
    protected String onRequestFinish(String result) {
          //这里可以实现对 json 数据的解析,例如使用 JSONObject 
          //对象解析具体的业务
        return result;
    }

    @Override
    protected String onRequestError(int code, String message) {
        return message;
    }
}

 

测试请求框架

request = new SimpleTextRequest(this, null);
        request.request()
                .subscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(@NonNull String s) throws Exception {
                        textView.setText(s);
                          //这里返回接口请求的数据
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        textView.setText(throwable.getMessage());
                    }
                });

 

本文运行的结果

request-demo

 

项目地址:https://github.com/wecodexyz/Componentization

微信关注我们,可以获取更多

目录
相关文章
|
9月前
|
JavaScript
Vue中Axios网络请求封装-企业最常用封装模式
本教程介绍如何安装并配置 Axios 实例,包含请求与响应拦截器,实现自动携带 Token、错误提示及登录状态管理,适用于 Vue 项目。
346 1
|
11月前
|
数据采集 算法 数据挖掘
模块化控制协议(MCP)在网络中增强智能体执行效率的研究
随着Web3技术的迅速发展,去中心化应用和智能体在各种领域的应用逐渐增多。MCP(Modularized Control Protocol,模块化控制协议)作为一种增强智能体执行能力的关键技术,为Web3场景中的智能体提供了更强的灵活性和可扩展性。本文将探讨如何利用MCP技术提升智能体在Web3场景中的执行能力,并通过实例代码展示其实现路径。
1017 22
|
11月前
|
移动开发 前端开发 JavaScript
鸿蒙NEXT时代你所不知道的全平台跨端框架:CMP、Kuikly、Lynx、uni-app x等
本篇基于当前各大活跃的跨端框架的现状,对比当前它们的情况和未来的可能,帮助你在选择框架时更好理解它们的特点和差异。
1082 0
|
9月前
|
JSON 自然语言处理 数据格式
使用Tabs选项卡组件快速搭建鸿蒙APP框架
ArkUI提供了很多布局组件,其中Tabs选项卡组件可以用于快速搭建鸿蒙APP框架,本文通过案例研究Tabs构建鸿蒙原生应用框架的方法和步骤。
576 5
使用Tabs选项卡组件快速搭建鸿蒙APP框架
|
9月前
|
存储 开发者 容器
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
本文介绍了ArkTS语言中的Class类、泛型、接口、模块化、自定义组件及状态管理等核心概念,并结合代码示例讲解了对象属性、构造方法、继承、静态成员、访问修饰符等内容,同时涵盖了路由管理、生命周期和Stage模型等应用开发关键知识点。
593 1
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
|
机器学习/深度学习 存储 人工智能
MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
MNN-LLM App 是阿里巴巴基于 MNN-LLM 框架开发的 Android 应用,支持多模态交互、多种主流模型选择、离线运行及性能优化。
15290 81
MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
《仿盒马》app开发技术分享-- 兑换订单列表框架(75)
上一节我们针对订单兑换的业务逻辑进行了完善,成功的在兑换物品之后修改了用户信息的修改,新增了积分消费的记录。这一节我们实现订单创建之后进入的列表展示页框架。
183 0
|
存储 文件存储 Android开发
仿第八区APP分发下载打包封装系统源码
该系统为仿第八区APP分发下载打包封装系统源码,支持安卓、iOS及EXE程序分发,自动判断并稳定安装。智能提取应用信息,自动生成PLIST文件和图标,提供合理的点数扣除机制。支持企业签名在线提交、专属下载页面生成、云端存储(阿里云、七牛云),并优化签名流程,支持中文包及合并分发,确保高效稳定的下载体验。 [点击查看源码](https://download.csdn.net/download/huayula/90463452)
826 22
|
安全 网络协议 Java
Java网络编程封装
Java网络编程封装原理旨在隐藏底层通信细节,提供简洁、安全的高层接口。通过简化开发、提高安全性和增强可维护性,封装使开发者能更高效地进行网络应用开发。常见的封装层次包括套接字层(如Socket和ServerSocket类),以及更高层次的HTTP请求封装(如RestTemplate)。示例代码展示了如何使用RestTemplate简化HTTP请求的发送与处理,确保代码清晰易维护。
|
Java 测试技术 持续交付
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
本文重点讲解如何搭建App自动化测试框架的思路,而非完整源码。主要内容包括实现目的、框架设计、环境依赖和框架的主要组成部分。适用于初学者,旨在帮助其快速掌握App自动化测试的基本技能。文中详细介绍了从需求分析到技术栈选择,再到具体模块的封装与实现,包括登录、截图、日志、测试报告和邮件服务等。同时提供了运行效果的展示,便于理解和实践。
1336 4
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路

热门文章

最新文章