StraightFromCacheSample.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using System;
  2. using System.Threading.Tasks;
  3. using Best.HTTP.Caching;
  4. using Best.HTTP.Examples.Helpers;
  5. using Best.HTTP.Shared;
  6. using UnityEngine;
  7. namespace Best.HTTP.Examples
  8. {
  9. class StraightFromCacheSample : SampleBase
  10. {
  11. #pragma warning disable 0649, 0169
  12. [Header("Sample Fields")]
  13. /// <summary>
  14. /// GameObject that will be used as a root for new UI objects.
  15. /// </summary>
  16. [SerializeField]
  17. private RectTransform _contentRoot;
  18. /// <summary>
  19. /// Prefab of a UI object with two Text fields.
  20. /// </summary>
  21. [SerializeField]
  22. private MultiTextListItem _listItemPrefab;
  23. /// <summary>
  24. /// Prefab of a UI object with Text and (Raw)Image fields.
  25. /// </summary>
  26. [SerializeField]
  27. private TextWithImageListItem _listItemWithImagePrefab;
  28. #pragma warning restore
  29. /// <summary>
  30. /// Address of the used end point.
  31. /// </summary>
  32. #if UNITY_ANDROID && !UNITY_EDITOR
  33. private string _baseAddress = "https://besthttpwebgldemo.azurewebsites.net/AssetBundles/Android/demobundle.assetbundle";
  34. #else
  35. private string _baseAddress = "https://besthttpwebgldemo.azurewebsites.net/AssetBundles/WebGL/demobundle.assetbundle";
  36. #endif
  37. protected override async void Start()
  38. {
  39. base.Start();
  40. var uri = new Uri(this._baseAddress);
  41. CreateUIItem("Calling await LoadImageFromLocalCacheAsync");
  42. // Try load the bundle and texture from local cache
  43. var texture = await LoadImageFromLocalCacheAsync(uri);
  44. // If it fails, download
  45. if (texture == null)
  46. {
  47. CreateUIItem("Content isn't cached yet! Downloading....");
  48. await DownloadIntoLocalCache(uri);
  49. CreateUIItem("Done! Retrying LoadImageFromLocalCacheAsync");
  50. texture = await LoadImageFromLocalCacheAsync(uri);
  51. }
  52. if (texture == null)
  53. CreateUIItem("Couldn't load image!");
  54. else
  55. CreateUIItemWithImage("Image loaded!")
  56. .SetImage(texture);
  57. }
  58. async Task DownloadIntoLocalCache(Uri uri)
  59. {
  60. var request = HTTPRequest.CreateGet(uri);
  61. // No content will be stored in memory.
  62. request.DownloadSettings.CacheOnly = true;
  63. try
  64. {
  65. await request.GetHTTPResponseAsync();
  66. }
  67. catch (AsyncHTTPException ex)
  68. {
  69. Debug.LogException(ex);
  70. }
  71. }
  72. #if UNITY_2023_1_OR_NEWER
  73. async
  74. #endif
  75. Task<Texture2D> LoadImageFromLocalCacheAsync(Uri uri)
  76. {
  77. #if UNITY_2023_1_OR_NEWER
  78. // If Setup isn't called yet, HTTPManager.LocalCache isn't created yet either and would be null.
  79. HTTPManager.Setup();
  80. var hash = HTTPCache.CalculateHash(HTTPMethods.Get, uri);
  81. // Call BeginReadContent to try to acquire a Stream to the cached content
  82. var stream = HTTPManager.LocalCache.BeginReadContent(hash, null);
  83. if (stream == null)
  84. return null;
  85. try
  86. {
  87. var bundleLoadAsyncOp = AssetBundle.LoadFromStreamAsync(stream);
  88. // Unity's GetAwaiter extension is typeless, we can await it but can't await and return with the asset bundle.
  89. // See "Loading resources asynchronously" at https://docs.unity3d.com/2023.2/Documentation/Manual/AwaitSupport.html
  90. await Awaitable.FromAsyncOperation(bundleLoadAsyncOp);
  91. var assetBundle = bundleLoadAsyncOp.assetBundle;
  92. var resourceLoadAsyncOp = assetBundle.LoadAssetAsync<Texture2D>("9443182_orig");
  93. await Awaitable.FromAsyncOperation(resourceLoadAsyncOp);
  94. return resourceLoadAsyncOp.asset as Texture2D;
  95. }
  96. finally
  97. {
  98. // If we called BeginReadContent and it's returned with a non-null value, we have to call EndReadContent too!
  99. HTTPManager.LocalCache.EndReadContent(hash, null);
  100. // We are responsible disposing the stream!
  101. stream?.Dispose();
  102. }
  103. #else
  104. return null;
  105. #endif
  106. }
  107. private void OnDestroy()
  108. => AssetBundle.UnloadAllAssetBundles(true);
  109. MultiTextListItem CreateUIItem(string str)
  110. => Instantiate<MultiTextListItem>(this._listItemPrefab, this._contentRoot)
  111. .SetText(str) as MultiTextListItem;
  112. TextWithImageListItem CreateUIItemWithImage(string str)
  113. => Instantiate<TextWithImageListItem>(this._listItemWithImagePrefab, this._contentRoot)
  114. .SetText(str) as TextWithImageListItem;
  115. }
  116. }