【Unity-学习-021】异步实现HTTP请求

对Http访问操作,Unity中一般使用协程操作,但是协程有一个比较要命的要求就是所在Mono必须在场景中是激活的,所以一些操作就会被限制。所以我们就找办法替代掉协程做一些异步的操作。那就用异步方法。

        首先扩展一下AsyncOperation类型。

    //扩展方法应该写在静态类里
    public static class HttpPlus
    {
        /// <summary>
        /// 异步重载
        /// </summary>
        /// <param name="asyncOp"></param>
        /// <returns></returns>
        public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp)
        {
            var tcs = new TaskCompletionSource<object>();
            asyncOp.completed += obj => { tcs.SetResult(null); };
            return ((Task) tcs.Task).GetAwaiter();
        }
    }

        然后就开始编写HTTP请求代码。

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Networking;


public class DownloadDataHandle
{
    public int code;
    public string msg;
    public object data;
}

public class MNull
{
}



public static class HttpPlus
{
    /// <summary>
    /// 异步重载
    /// </summary>
    /// <param name="asyncOp"></param>
    /// <returns></returns>
    public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp)
    {
        var tcs = new TaskCompletionSource<object>();
        asyncOp.completed += obj => { tcs.SetResult(null); };
        return ((Task) tcs.Task).GetAwaiter();
    }
}



public class HttpManager
{
    /// <summary>
    /// 异步Get
    /// </summary>
    /// <param name="uri"></param>
    /// <param name="toDo">数据获取之后执行的回调</param>
    /// <typeparam name="T"></typeparam>
    internal async void GetAsync<T>(string uri, Action<T, DownloadDataHandle> toDo = null)
    {
        using var webRequest = UnityWebRequest.Get(uri);
        await webRequest.SendWebRequest();
        switch (webRequest.result)
        {
            case UnityWebRequest.Result.ConnectionError:
            case UnityWebRequest.Result.DataProcessingError:
            case UnityWebRequest.Result.ProtocolError:
            case UnityWebRequest.Result.InProgress:
                try
                {
                    var handle1 = JsonConvert.DeserializeObject<DownloadDataHandle>(webRequest.downloadHandler.text);
                    toDo?.Invoke(default, handle1);
                }
                catch (Exception e)
                {
                    Debug.Log(webRequest.error + "  url : " + uri);
                }

                break;
            case UnityWebRequest.Result.Success:
                try
                {
                    var handle = JsonConvert.DeserializeObject<DownloadDataHandle>(webRequest.downloadHandler.text);
                    var t = typeof(T) == typeof(MNull) ? default : JsonConvert.DeserializeObject<T>(handle.data.ToString());
                    toDo?.Invoke(t, handle);
                }
                catch (Exception e)
                {
                    Debug.Log("e : " + e);
                }

                break;
        }
    }

    /// <summary>
    /// 异步获取图片
    /// </summary>
    /// <param name="uri">地址</param>
    /// <param name="size">传进来的图片尺寸</param>
    /// <param name="toDo">把sprite和Texture2D一起返回方便管理(在使用后销毁)</param>
    internal async void GetImg(string uri, Vector2Int size, Action<Sprite, Texture2D> toDo = null)
    {
        using var webRequest = UnityWebRequest.Get(uri);
        await webRequest.SendWebRequest();
        switch (webRequest.result)
        {
            case UnityWebRequest.Result.InProgress:
            case UnityWebRequest.Result.ConnectionError:
            case UnityWebRequest.Result.ProtocolError:
            case UnityWebRequest.Result.DataProcessingError:
                Debug.Log(webRequest.error + "  url : " + uri);
                break;
            case UnityWebRequest.Result.Success:
                // 先获取到图片的数据
                byte[] results = webRequest.downloadHandler.data;
                // 创建一个 Texture,这个尺寸根据自己需要而定
                Texture2D texture = new Texture2D(size.x, size.y);
                texture.LoadImage(results);
                await Task.Delay(10);
                // 使用 Texture 创建一个sprite
                Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
                toDo?.Invoke(sprite, texture);
                break;
        }
    }

    /// <summary>
    /// 异步Post
    /// </summary>
    /// <param name="uri">地址</param>
    /// <param name="form">表单</param>
    /// <param name="header">头</param>
    /// <param name="toDo">数据上传之后执行的回调</param>
    /// <typeparam name="T"></typeparam>
    internal async void PostAsync<T>(string uri, WWWForm form, Dictionary<string, string> header = null, Action<T, DownloadDataHandle> toDo = null)
    {
        using var webRequest = UnityWebRequest.Post(uri, form);
        if (header != null)
        {
            foreach (var item in header)
            {
                webRequest.SetRequestHeader(item.Key, item.Value);
            }
        }

        await webRequest.SendWebRequest();
        switch (webRequest.result)
        {
            case UnityWebRequest.Result.ConnectionError:
            case UnityWebRequest.Result.DataProcessingError:
            case UnityWebRequest.Result.InProgress:
            case UnityWebRequest.Result.ProtocolError:
                try
                {
                    var handle = JsonConvert.DeserializeObject<DownloadDataHandle>(webRequest.downloadHandler.text);
                    toDo?.Invoke(default, handle);
                }
                catch (Exception e)
                {
                    Debug.Log(webRequest.error + "  ,  " + uri + "  e : " + e);
                }

                break;
            case UnityWebRequest.Result.Success:
                try
                {
                    var handle = JsonConvert.DeserializeObject<DownloadDataHandle>(webRequest.downloadHandler.text);
                    var t = typeof(T) == typeof(MNull) ? default : JsonConvert.DeserializeObject<T>(handle.data.ToString());
                    toDo?.Invoke(t, handle);
                }
                catch (Exception e)
                {
                    Debug.LogError("e : " + e);
                }

                break;
        }
    }
}

这样就可以了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ThursdayGame

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值