Unity UnityWebRequest封装类

news2024/9/29 16:29:36

简化api调用流程,非常奈斯。

RestWebClient.cs

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

namespace MYTOOL.RestClient
{
    /// <summary>
    /// UnityWebRequest封装类
    /// </summary>
    public class RestWebClient
    {
        private readonly MonoBehaviour executer;

        public RestWebClient(MonoBehaviour executer)
        {
            if (executer == null) throw new ArgumentNullException();
            this.executer = executer;
        }

        #region >> GET

        public Coroutine Get(string url, Request req)
        {
            if (req == null) throw new ArgumentNullException();
            return executer.StartCoroutine(InnerGet(url, req));
        }

        #endregion


        #region >> PUT

        public Coroutine Put(string url, Request req)
        {
            if (req == null) throw new ArgumentNullException();
            return executer.StartCoroutine(InnerPut(url, req));
        }

        #endregion


        #region >> POST

        public Coroutine Post(string url, Request req)
        {
            if (req == null) throw new ArgumentNullException();
            return executer.StartCoroutine(InnerPost(url, req));
        }

        public Coroutine PostForm(string url, WWWForm formData, Request req)
        {
            if (req == null) throw new ArgumentNullException();
            return executer.StartCoroutine(InnerPostForm(url, formData, req));
        }

        #endregion


        #region >> DELETE

        public Coroutine Delete(string url, Request req)
        {
            if (req == null) throw new ArgumentNullException();
            return executer.StartCoroutine(InnerDelete(url, req));
        }

        #endregion


        private IEnumerator InnerGet(string url, Request req)
        {
            req.OnBegin?.Invoke();

            ushort retryCount = req.RetryCount;
            do
            {
                using UnityWebRequest webRequest = UnityWebRequest.Get(url);
                InitUnityWebRequest(webRequest, req);
                yield return webRequest.SendWebRequest();

                bool isSuccess = webRequest.result == UnityWebRequest.Result.Success;
                if (isSuccess || retryCount == 0)
                {
                    if (DebugMode) LogInfo("GET", webRequest.responseCode, isSuccess, webRequest.url);
                    req.Invoke(isSuccess, webRequest.responseCode, webRequest.downloadHandler.data, webRequest.error);
                    yield break;
                }
                if (req.RetryInterval > 0)
                {
                    yield return new WaitForSeconds(req.RetryInterval);
                }
            } while (retryCount-- > 0);
        }

        private IEnumerator InnerPut(string url, Request req)
        {
            req.OnBegin?.Invoke();

            ushort retryCount = req.RetryCount;
            do
            {
                using UnityWebRequest webRequest = UnityWebRequest.Put(url, req.BodyData);
                InitUnityWebRequest(webRequest, req);
                yield return webRequest.SendWebRequest();

                bool isSuccess = webRequest.result == UnityWebRequest.Result.Success;
                if (isSuccess || retryCount == 0)
                {
                    if (DebugMode) LogInfo("PUT", webRequest.responseCode, isSuccess, webRequest.url);
                    req.Invoke(isSuccess, webRequest.responseCode, webRequest.downloadHandler.data, webRequest.error);
                    yield break;
                }
                if (req.RetryInterval > 0)
                {
                    yield return new WaitForSeconds(req.RetryInterval);
                }
            } while (retryCount-- > 0);
        }

        private IEnumerator InnerPost(string url, Request req)
        {
            req.OnBegin?.Invoke();

            ushort retryCount = req.RetryCount;
            do
            {
                using UnityWebRequest webRequest = UnityWebRequest.Post(url, req.BodyData);
                InitUnityWebRequest(webRequest, req);
                yield return webRequest.SendWebRequest();

                bool isSuccess = webRequest.result == UnityWebRequest.Result.Success;
                if (isSuccess || retryCount == 0)
                {
                    if (DebugMode) LogInfo("POST", webRequest.responseCode, isSuccess, webRequest.url);
                    req.Invoke(isSuccess, webRequest.responseCode, webRequest.downloadHandler.data, webRequest.error);
                    yield break;
                }
                if (req.RetryInterval > 0)
                {
                    yield return new WaitForSeconds(req.RetryInterval);
                }

            } while (retryCount-- > 0);

        }

        private IEnumerator InnerPostForm(string url, WWWForm formData, Request req)
        {
            req.OnBegin?.Invoke();

            ushort retryCount = req.RetryCount;
            do
            {
                using UnityWebRequest webRequest = UnityWebRequest.Post(url, formData);
                InitUnityWebRequest(webRequest, req);
                yield return webRequest.SendWebRequest();

                bool isSuccess = webRequest.result == UnityWebRequest.Result.Success;
                if (isSuccess || retryCount == 0)
                {
                    if (DebugMode) LogInfo("POST", webRequest.responseCode, isSuccess, webRequest.url);
                    req.Invoke(isSuccess, webRequest.responseCode, webRequest.downloadHandler.data, webRequest.error);
                    yield break;
                }
                if (req.RetryInterval > 0)
                {
                    yield return new WaitForSeconds(req.RetryInterval);
                }
            } while (retryCount-- > 0);
        }

        private IEnumerator InnerDelete(string url, Request req)
        {
            req.OnBegin?.Invoke();

            ushort retryCount = req.RetryCount;
            do
            {
                using UnityWebRequest webRequest = UnityWebRequest.Delete(url);
                webRequest.downloadHandler = new DownloadHandlerBuffer();
                InitUnityWebRequest(webRequest, req);
                yield return webRequest.SendWebRequest();

                bool isSuccess = webRequest.result == UnityWebRequest.Result.Success;
                if (isSuccess || retryCount == 0)
                {
                    if (DebugMode) LogInfo("DELETE", webRequest.responseCode, isSuccess, webRequest.url);
                    req.Invoke(isSuccess, webRequest.responseCode, webRequest.downloadHandler.data, webRequest.error);
                    yield break;
                }
                if (req.RetryInterval > 0)
                {
                    yield return new WaitForSeconds(req.RetryInterval);
                }
            } while (retryCount-- > 0);
        }

        private void InitUnityWebRequest(UnityWebRequest webRequest, Request req)
        {
            webRequest.timeout = req.Timeout;
            if (webRequest.uploadHandler != null && string.IsNullOrEmpty(req.ContentType) == false)
            {
                webRequest.uploadHandler.contentType = req.ContentType;
            }

            var queryString = req.GetQueryString();
            if (string.IsNullOrEmpty(queryString) == false)
            {
                if (webRequest.url.EndsWith('?'))
                {
                    webRequest.url += queryString;
                }
                else
                {
                    webRequest.url += $"?{queryString}";
                }
            }

            var headers = req.GetHeaders();
            foreach (var header in headers)
            {
                webRequest.SetRequestHeader(header.Key, header.Value);
            }
        }


        public static bool DebugMode = true;
        private static void LogInfo(string method, long code, bool success, string info)
        {
            string str = success ? $"<color=green>{info}</color>" : $"<color=red>{info}</color>";
            Debug.Log($"[{method}] [{code}] => {str}");
        }
    }
}

Request.cs

using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;

namespace MYTOOL.RestClient
{
    public class Request
    {
        public const string APPLICATION_JSON = "application/json";

        /// <summary>
        /// 超时时间
        /// </summary>
        public int Timeout { get; private set; }
        /// <summary>
        /// 重试次数
        /// </summary>
        public ushort RetryCount { get; private set; }
        /// <summary>
        /// 重试间隔(秒)
        /// </summary>
        public float RetryInterval { get; private set; }
        /// <summary>
        /// 内容
        /// </summary>
        public string BodyData { get; private set; }
        /// <summary>
        /// 内容类型
        /// </summary>
        public string ContentType { get; private set; }
        /// <summary>
        /// 请求是否完成
        /// </summary>
        public bool IsDone { get; private set; }

        /// <summary>
        /// 请求开始前的回调
        /// </summary>
        public Action OnBegin;
        /// <summary>
        /// 请求完成后的回调
        /// </summary>
        private readonly Action<Response> OnComplete;

        private readonly Dictionary<string, string> Headers;
        private readonly Dictionary<string, List<string>> Query;

        public Request(Action<Response> onComplete, int timeout = 10)
        {
            OnComplete = onComplete;
            Timeout = timeout;
            Headers = new Dictionary<string, string>();
            Query = new Dictionary<string, List<string>>();
        }

        public Request(Action<Response> onComplete, string bodyData, int timeout = 10) : this(onComplete, timeout)
        {
            BodyData = bodyData;
        }

        public Request Reset()
        {
            IsDone = false;
            return this;
        }

        internal void Invoke(bool succeed, long statusCode, byte[] data, string error)
        {
            IsDone = true;
            OnComplete?.Invoke(new Response(succeed, statusCode, data, error));
        }

        public Request AddQuery(string key, string value)
        {
            if (Query.ContainsKey(key) == false)
            {
                Query[key] = new List<string>();
            }

            Query[key].Add(value);
            return this;
        }

        public bool RemoveQuery(string key)
        {
            return Query.Remove(key);
        }

        public Request SetRequestHeader(string key, string value)
        {
            Headers[key] = value;
            return this;
        }

        public Dictionary<string, string> GetHeaders()
        {
            return new Dictionary<string, string>(Headers);
        }

        public string GetQueryString()
        {
            StringBuilder sb = new StringBuilder();

            foreach (var kv in Query)
            {
                if (sb.Length > 0 && kv.Value.Count > 0) sb.Append('&');

                // 将每个键值对转换为字符串并连接起来
                var values = string.Join('&', kv.Value.Select(value => $"{kv.Key}={value}"));
                sb.Append(values);
            }

            return sb.ToString();
        }
        /// <summary>
        /// 设置超时时间
        /// </summary>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public Request SetTimeout(int timeout)
        {
            Timeout = timeout;
            return this;
        }
        /// <summary>
        /// 设置重试参数
        /// </summary>
        /// <param name="retryCount">重试次数</param>
        /// <param name="sec">重试间隔(秒)</param>
        /// <returns></returns>
        public Request SetRetryOption(ushort retryCount, float retryInterval)
        {
            RetryCount = retryCount;
            RetryInterval = retryInterval;
            return this;
        }
        /// <summary>
        /// 设置Body内容
        /// </summary>
        /// <param name="bodyData"></param>
        /// <returns></returns>
        public Request SetBodyData(string bodyData)
        {
            BodyData = bodyData;
            return this;
        }
        /// <summary>
        /// 设置Body内容,并指定内容类型
        /// </summary>
        /// <param name="bodyData"></param>
        /// <param name="contentType">如:application/json</param>
        /// <returns></returns>
        public Request SetBodyData(string bodyData, string contentType)
        {
            BodyData = bodyData;
            ContentType = contentType;
            return this;
        }
        /// <summary>
        /// 设置内容类型
        /// </summary>
        /// <param name="contentType">如:application/json</param>
        /// <returns></returns>
        public Request SetContentType(string contentType)
        {
            ContentType = contentType;
            return this;
        }
    }
}

Response.cs

using System.Text;

namespace MYTOOL.RestClient
{
    public class Response
    {
        public bool Succeed { get; }

        public long StatusCode { get; }

        public byte[] Data { get; }
        public string Error { get; }

        public bool HasError => string.IsNullOrEmpty(Error) == false;

        public Response(bool succeed, long statusCode, byte[] data, string error)
        {
            Succeed = succeed;
            StatusCode = statusCode;
            Data = data;
            Error = error;
        }

        public string GetResponseData(Encoding encoding = null)
        {
            if (Data == null) return "";

            encoding ??= Encoding.UTF8;
            return encoding.GetString(Data);
        }
    }
}

使用例子

using MYTOOL.RestClient;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    private RestWebClient client;

    private void Awake()
    {
        //初始化
        client = new RestWebClient(this);
    }

    private void Start()
    {
        //设置请求完成后回调 与 超时时间
        Request req = new Request(OnGetBaidu, 30);
        //设置重试次数 与 重试间隔
        req.SetRetryOption(3, 0.2f);
        client.Get("https://www.baidu.com/", req);
    }

    void OnGetBaidu(Response resp)
    {
        if (resp.Succeed)
        {
            if (resp.StatusCode == 200 || resp.StatusCode == 204)
            {
                Debug.Log($"请求成功,{resp.GetResponseData()}");
            }
        }
        else
        {
            Debug.Log($"请求失败,{resp.Error}");
        }
    }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1979960.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于R语言绘制GGE双标图1

参考资料&#xff1a; 严威凯等: 双标图分析在农作物品种多点试验中的应用【作物学报】 https://cran.r-project.org/web/packages/GGEBiplots/GGEBiplots.pdf 1、安装GGEBiplots包 目前搜索到的资料多数为“GGEBiplotGUI”安装包&#xff0c;但在安装时报错&#xff0c;如下…

【独家原创】基于APO-Transformer-LSTM多特征分类预测(多输入单输出)Matlab代码

【独家原创】基于APO-Transformer-LSTM多特征分类预测&#xff08;多输入单输出&#xff09;Matlab代码 目录 【独家原创】基于APO-Transformer-LSTM多特征分类预测&#xff08;多输入单输出&#xff09;Matlab代码分类效果基本描述程序设计参考资料 分类效果 基本描述 [24年最…

【初阶数据结构题目】11.相交链表

相交链表 点击链接做题 思路&#xff1a; 如何判断链表是否相交找相交链表的起始节点 遍历两个链表&#xff0c;若尾结点相同&#xff0c;则链表一定相交。两个链表节点个数相同&#xff1a;往后遍历&#xff0c;找到相交的位置两个链表节点个数不同&#xff1a; 找两个链表的…

End-to-End Object Detection with Transformers(Detection Transformer)翻译

摘要 我们提出了一种新方法&#xff0c;将目标检测视为直接的集合预测问题。我们的方法简化了检测流程&#xff0c;有效消除了对许多手工设计组件的需求&#xff0c;如非极大值抑制过程或锚框生成&#xff0c;这些组件显式编码了我们对任务的先验知识。新框架称为检测变换器&a…

Meta Reality Labs:巨额亏损背后的挑战与展望

一、财务概况 自2020年以来,Meta的Reality Labs部门累计亏损已超过450亿美元,其中2023年的亏损达到160亿美元,2024年第一季度亏损38亿美元,分析师预计第二季度亏损可能接近50亿美元。尽管投入巨大,Reality Labs的收入却呈现下降趋势,与不断增加的支出形成鲜明对比。 二…

QT使用V4L2摄像头采集数据

前言 之前我们已经实现了摄像头用V4L2框架采集一张图片&#xff0c;现在就是实现用摄像头采集视频流&#xff08;本质一张图片就是一帧&#xff0c;很多张图片就是很多帧&#xff0c;拼起来就是一个视频&#xff09;。 本部分需要大家有一点QT相关的知识&#xff0c;整体框架还…

CSP 2020 第三题:表达式

牛客网题目 题目内容&#xff1a; 示例1 输入 x1 x2 & x3 | 3 1 0 1 3 1 2 3输出 1 1 0题意&#xff1a; 给出后续表达式&#xff0c;需要计算这个表达式的值&#xff0c;并让某几个变量值取反&#xff0c;再输出新的表达式的值&#xff08;变量改变均为临时的&#xff…

基于Orangepi全志H616学习Python3

目录 一、功能需求 二、Python的安装和环境搭建 三、Python的基础学习 3.1 Python的特点&#xff1a; 3.2 编写并运行第一个Python程序&#xff1a; 3.3 标识符&#xff1a; 3.4 关键字&#xff1a; 3.5 注释&#xff1a; 3.6 行与缩进&#xff1a; 3.7 多行语句&…

虚拟机(CentOS7)安装jenkins

centos7安装jenkins 前提条件&#xff0c;安装jdk与maven 1、JDK17安装 # 进入系统管理员 sudo root # 进入对应文件夹下 cd /usr/local # 下载jdk17 wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm # rpm命令安装下载的jdk17 rpm -ivh jdk-17_li…

从根儿上学习spring 七 之run方法启动第四段(1)

图1 一步一步我们转眼间来到了第四部分&#xff0c;这是spring最核心的部分包含了bean的整个生命周期过程&#xff0c;不过大家不用担心如果内容过长我会分多个小节来说明以防止一篇文章让大家看晕看累难以吸收理解。让我们直接进入正题。 我们先进入图1的refreshContext方法看…

PEX实验

一、kickstart自动安装脚本制作 1.关闭本机dhcp服务 2.安装图形化生成kickstart自动安装脚本的工具 3.配置http服务 下载httpd 启动并挂载 3.启动图形制作工具 system-config-kickstart 4.配置ks.cfg 5.拷贝到/var/www/html/中去 6.浏览器测试 配置dhcp服务 测试 二.搭建pex…

【JVM基础11】——垃圾回收-说一下JVM的分代回收?

目录 1- 引言&#xff1a;分代回收1-1 什么是分代回收&#xff08;What&#xff09;1-2 为什么要用分代回收&#xff1f;&#xff08;Why&#xff09; 2- ⭐核心&#xff1a;分代回收工作机制2-1 工作机制2-2 MinorGC、Mixed GC、FullGC的区别是什么 3- 总结3-1 说一下 JVM 的分…

【Java 第三篇章】注释、数据类型、运算符

一、注释 Java 中的注释有三种方式&#xff1a;单行注释、多行注释、文档注释。 1、单行注释语法 // 这是单行注释2、多行注释 /** 这是多行注释*/3、文档注释 /*** 这是文档注释*/二、数据类型 Java 中有 8 中基本数据类型&#xff0c;分别为&#xff1a;整型&#xff08;b…

数据结构实验报告-排序

桂 林 理 工 大 学 实 验 报 告 一、实验名称 实验8 排序 二、实验内容&#xff1a; 分别采用直接插人排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序等排序算法对简单的整型数组进行排序,并输出排序结果。 源码&#xff1a;#include <iostre…

分享一个简单线性dp

我们可以o(n^2)&#xff0c;枚举每一个布告&#xff0c;然后从后往前枚举i前面的位置&#xff0c;然后状态转移 void solve() {int n;cin >> n;vector<int> a(n 1);for (int i 1; i < n; i) cin >> a[i];vector<int> f(n 1, 0x3f3f3f3f);f[0] …

【分隔链表】python刷题记录

R3-双指针&#xff08;快慢指针&#xff09; 新建两个链表 一个链表记录<x的值 一个链表记录>x的值 拼接即可 # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next ne…

C语言 | Leetcode C语言题解之第322题零钱兑换

题目&#xff1a; 题解&#xff1a; int coinChange(int* coins, int coinsSize, int amount) {int dp[coinsSize1][amount1];for(int i0;i<coinsSize;i){for(int j0;j<amount;j){dp[i][j]INT_MAX-1;//初始化值为INT_MAX-1&#xff0c;避免后续加一导致溢出}}for(int i0;…

Python | Leetcode Python题解之第321题拼接最大数

题目&#xff1a; 题解&#xff1a; class Solution:def maxNumber(self, nums1: List[int], nums2: List[int], k: int) -> List[int]:m, n len(nums1), len(nums2)maxSubsequence [0] * kstart, end max(0, k - n), min(k, m)for i in range(start, end 1):subsequen…

语言无界,沟通无限:2024年好用在线翻译工具推荐

随着技术的发展现在的翻译在线工具从基础词句翻译到复杂的文章翻译都不在话下。为了防止你被五花八门的工具挑花眼&#xff0c;我给你介绍几款我用过的便捷、高效、准确的翻译工具吧。 1.福晰翻译端 链接直通&#xff1a;https://www.foxitsoftware.cn/fanyi/ 这个软件支持…

Google上架:8月份政策改动,未在8月31日前回应做出改动的包体将会有下架的风险

谷歌一直以用户为中心的服务思想,政策一直在变动,未及时变动的包体又下架甚至封号的风险,如有以下情况,请及时检查包体或账号相关问题,希望能给各位开发者带来帮助。 截止提交时间 2024-08-31 支付相关要求变动公布日期改动须知更改要求垃圾应用包体与用户体验公布日期改动…