赞
踩
UE提供了BlueprintAsyncActionBase类,实现异步加载的方式请求数据
虚幻的很多蓝图节点都采用了异步加载的方式
比如:延迟Delay,PlayMontage都是采用异步加载的方式进行实现
接下我们就用异步加载的方式实现HTTP请求下载
新建一个C++项目,然后build.cs加入模块
PrivateDependencyModuleNames.AddRange(new string[] { "HTTP", "Json" });
创建继承自BlueprintAsyncActionBase的C++类
请求的Json格式的数据为
代理声明:代理参数跟我们后面函数的输出参数有关,要想输出函数参数,需要在代理的位置声明返回参数
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FRequestCompleteDelegate, const TArray<FNewsItem>&, Data,int32, ver);
输出节点如OnSucceeded,OnFailed这些节点跟我们声明的代理有关,就是代理声明的对象
- //输出节点
- UPROPERTY(BlueprintAssignable)
- FRequestCompleteDelegate OnSucceeded;
-
- //输出节点
- UPROPERTY(BlueprintAssignable)
- FRequestCompleteDelegate OnFailed;
主要代码如下MyBlueprintAsyncActionBase.h文件
- // Fill out your copyright notice in the Description page of Project Settings.
-
- #pragma once
-
- #include "CoreMinimal.h"
- #include "Kismet/BlueprintAsyncActionBase.h"
- #include "Interfaces/IHttpRequest.h"
- #include "MyBlueprintAsyncActionBase.generated.h"
-
-
- USTRUCT(BlueprintType)
- struct FNewsItem {
- GENERATED_USTRUCT_BODY()
-
- FNewsItem() {}
- FNewsItem(FString _Path, FString _Url)
- : Path(_Path), Url(_Url) {}
- UPROPERTY(BlueprintReadOnly)
- FString Path;
- UPROPERTY(BlueprintReadOnly)
- FString Url;
- };
-
- DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FRequestCompleteDelegate, const TArray<FNewsItem>&, Data,int32, ver);
-
-
- /**
- *
- */
- UCLASS()
- class TEST111_API UMyBlueprintAsyncActionBase : public UBlueprintAsyncActionBase
- {
- GENERATED_BODY()
-
- UMyBlueprintAsyncActionBase();
-
- //json
- public:
-
- // 自定义的异步蓝图节点
- UFUNCTION(BlueprintCallable, Category = "AsyncHttp", meta = (BlueprintInternalUseOnly = "true"))
- static UMyBlueprintAsyncActionBase* AsyncHttpURLRequest(const FString& url);
-
- void HttpRequestStar(const FString& url);
- void HttpRequest_RecHandle(FHttpRequestPtr request, FHttpResponsePtr response, bool bWasSuccessful);
-
- //输出节点
- UPROPERTY(BlueprintAssignable)
- FRequestCompleteDelegate OnSucceeded;
-
- //输出节点
- UPROPERTY(BlueprintAssignable)
- FRequestCompleteDelegate OnFailed;
-
-
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Version")
- int32 version;
-
- };
MyBlueprintAsyncActionBase.cpp文件
- // Fill out your copyright notice in the Description page of Project Settings.
-
-
- #include "MyBlueprintAsyncActionBase.h"
- #include "HttpModule.h"
- #include "Interfaces/IHttpResponse.h"
-
- UMyBlueprintAsyncActionBase::UMyBlueprintAsyncActionBase()
- {
- if (HasAnyFlags(RF_ClassDefaultObject) == false)
- {
- AddToRoot(); //防止自动GC
- }
- }
-
- UMyBlueprintAsyncActionBase* UMyBlueprintAsyncActionBase::AsyncHttpURLRequest(const FString& url) {
- UMyBlueprintAsyncActionBase* AsyncHttpObject = NewObject<UMyBlueprintAsyncActionBase>();
- AsyncHttpObject->HttpRequestStar(url);
- return AsyncHttpObject;
- }
-
- //开始请求
- void UMyBlueprintAsyncActionBase::HttpRequestStar(const FString& url)
- {
- TSharedRef<IHttpRequest, ESPMode::ThreadSafe> request = FHttpModule::Get().CreateRequest();
- request->SetVerb("GET");
- request->SetURL(url);
- //request->SetHeader(TEXT("Content-Type"), TEXT("application/json;charset=utf-8"));
- //request->SetTimeout(200);
- //request->SetContentAsString(requestJsonStr); POST时候用
- //request->OnRequestProgress().BindUObject() 绑定进度
- request->OnProcessRequestComplete().BindUObject(this, &UMyBlueprintAsyncActionBase::HttpRequest_RecHandle); //请求回调
- request->ProcessRequest();
- }
- //请求回调
- void UMyBlueprintAsyncActionBase::HttpRequest_RecHandle(FHttpRequestPtr request, FHttpResponsePtr response, bool bWasSuccessful) {
-
-
- if (bWasSuccessful && response.IsValid() && EHttpResponseCodes::IsOk(response->GetResponseCode())) {
- TSharedPtr<FJsonObject> jsonObj;
- TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<>::Create(response->GetContentAsString());
-
- if (FJsonSerializer::Deserialize(JsonReader, jsonObj)) {
- version = jsonObj->GetIntegerField("versionId");
- UE_LOG(LogTemp, Warning, TEXT("version is %d"), version);
- const TArray< TSharedPtr<FJsonValue> >* dataList;
- if (jsonObj->TryGetArrayField(TEXT("DataList"), dataList)) // 获取数组
- {
- TArray<FNewsItem> newsList;
- for (TSharedPtr<FJsonValue> item : *dataList)
- {
- TSharedPtr<FJsonObject>itemObjet = item->AsObject();
-
- newsList.Add(FNewsItem(
- itemObjet->GetStringField(TEXT("Path")),
- itemObjet->GetStringField(TEXT("Url"))
- ));
- }
- OnSucceeded.Broadcast(newsList, version); // 成功的执行
- RemoveFromRoot();
- return;
- }
- }
- }
- OnFailed.Broadcast({},0); // 失败的执行
- RemoveFromRoot();
- }
-
打开关卡蓝图:
这里我重新建了一个继承自BlueprintAsyncActionBase的类
TestBlueprintAsyncActionBase.h文件
- // Fill out your copyright notice in the Description page of Project Settings.
-
- #pragma once
-
- #include "CoreMinimal.h"
- #include "Kismet/BlueprintAsyncActionBase.h"
- #include "Interfaces/IHttpRequest.h"
- #include "TestBlueprintAsyncActionBase.generated.h"
-
-
- /**
- *
- */
- DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FDownloadProgressDelegate1,
- const int32&, ReceivedDataInBytes,
- const int32&, TotalDataInBytes,
- const TArray<uint8>&, BinaryData
- );
- DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDownloadDelegate1);
-
- UCLASS()
- class TEST111_API UTestBlueprintAsyncActionBase : public UBlueprintAsyncActionBase
- {
- GENERATED_BODY()
-
- UTestBlueprintAsyncActionBase();
- public:
- //load data
-
- UFUNCTION(BlueprintCallable, Category = "MyAsyncHttp", meta = (BlueprintInternalUseOnly = "true"))
- static UTestBlueprintAsyncActionBase* AsyncHttpDownload(const FString& url);
-
- void DownloadRequestStart(const FString& url);
- void DownloadRequestHandle(FHttpRequestPtr request, FHttpResponsePtr response, bool bWasSuccessful);
- void DownloadProgress(FHttpRequestPtr request, int32 bytesSent, int32 bytesReceived);
-
- //输出节点
- UPROPERTY(BlueprintAssignable)
- FDownloadProgressDelegate1 OnProgressUpdate; //最好把有参数的放在前面,不然参数在蓝图节点有时候被吃掉了
-
- //输出节点
- UPROPERTY(BlueprintAssignable)
- FDownloadDelegate1 Load_Ok;
-
- //输出节点
- UPROPERTY(BlueprintAssignable)
- FDownloadDelegate1 Load_Fail;
- };
TestBlueprintAsyncActionBase.cpp文件
- // Fill out your copyright notice in the Description page of Project Settings.
-
-
- #include "TestBlueprintAsyncActionBase.h"
- #include "HttpModule.h"
- #include "Interfaces/IHttpResponse.h"
-
- UTestBlueprintAsyncActionBase::UTestBlueprintAsyncActionBase()
- {
- if (HasAnyFlags(RF_ClassDefaultObject) == false)
- {
- AddToRoot(); //防止自动GC
- }
- }
-
- UTestBlueprintAsyncActionBase* UTestBlueprintAsyncActionBase::AsyncHttpDownload(const FString& url)
- {
- UTestBlueprintAsyncActionBase* AsyncHttpObject = NewObject<UTestBlueprintAsyncActionBase>();
- AsyncHttpObject->DownloadRequestStart(url);
- return AsyncHttpObject;
- }
-
- void UTestBlueprintAsyncActionBase::DownloadRequestStart(const FString& url)
- {
- TSharedRef<IHttpRequest, ESPMode::ThreadSafe> request = FHttpModule::Get().CreateRequest();
- request->SetVerb("GET");
- request->SetURL(url);
- request->OnProcessRequestComplete().BindUObject(this, &UTestBlueprintAsyncActionBase::DownloadRequestHandle); //请求回调
- request->OnRequestProgress().BindUObject(this, &UTestBlueprintAsyncActionBase::DownloadProgress);// 下载进度
- request->ProcessRequest();
-
- RemoveFromRoot(); // 手动GC
- }
-
- void UTestBlueprintAsyncActionBase::DownloadRequestHandle(FHttpRequestPtr request, FHttpResponsePtr response, bool bWasSuccessful)
- {
- RemoveFromRoot();
-
-
- if (bWasSuccessful && response.IsValid() && EHttpResponseCodes::IsOk(response->GetResponseCode()))
- {
- if (response->GetContentLength() > 0) {
- TArray<uint8> EmptyData;
- OnProgressUpdate.Broadcast(response->GetContentLength(), response->GetContentLength(), EmptyData);
- }
-
- FString FileSavePath = FPaths::ProjectDir() + "/download/gameplay.png";
- FString Path, Filename, Extension;
- FPaths::Split(FileSavePath, Path, Filename, Extension);
- IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
-
- if (!PlatformFile.DirectoryExists(*Path))
- {
- if (!PlatformFile.CreateDirectoryTree(*Path))
- {
- UE_LOG(LogTemp, Error, TEXT("Create Directory Failed!"));
- Load_Fail.Broadcast();
- return;
- }
- }
-
- IFileHandle* FileHandle = PlatformFile.OpenWrite(*FileSavePath);
- if (FileHandle)
- {
- FileHandle->Write(response->GetContent().GetData(), response->GetContentLength());
- delete FileHandle;
- Load_Ok.Broadcast();
- return;
- }
- else {
- UE_LOG(LogTemp, Error, TEXT("Save File Failed!"));
- Load_Fail.Broadcast();
- return;
- }
-
- }
- UE_LOG(LogTemp, Error, TEXT("download File Failed!"));
- Load_Fail.Broadcast();
- return;
- }
-
- void UTestBlueprintAsyncActionBase::DownloadProgress(FHttpRequestPtr request, int32 bytesSent, int32 bytesReceived)
- {
- if (request->GetResponse()->GetContentLength() > 0)
- {
- TArray<uint8> EmptyData;
- OnProgressUpdate.Broadcast(bytesReceived, request->GetResponse()->GetContentLength(), EmptyData);
- }
- }
-
-
打开关卡蓝图设置:
注意这里图片下载的位置在项目工程里新建了一个download的文件夹里面
FString FileSavePath = FPaths::ProjectDir() + "/download/gameplay.png";
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。