Skip to content

Commit e50fab8

Browse files
committed
Updated README
1 parent c6c8ccb commit e50fab8

File tree

1 file changed

+134
-28
lines changed

1 file changed

+134
-28
lines changed

README.md

Lines changed: 134 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@ Async image loader with two caching layers for Unity. It supports loading images
77

88
Wait for image get loaded then set:
99

10-
``` C#
10+
```csharp
1111
image.sprite = await ImageLoader.LoadSprite(imageURL);
1212
```
1313

1414
Don't wait, use callback to set loaded image later:
1515

16-
``` C#
16+
```csharp
1717
ImageLoader.LoadSprite(imageURL).ThenSet(image).Forget();
1818
```
1919

2020
Use callback to set image and still wait for the completion:
2121

22-
``` C#
22+
```csharp
2323
await ImageLoader.LoadSprite(imageURL).ThenSet(image);
2424
```
2525

@@ -77,8 +77,15 @@ await ImageLoader.LoadSprite(imageURL).ThenSet(image);
7777
- [Get references count](#get-references-count)
7878
- [Other](#other)
7979
- [Understanding `IFuture<T>`](#understanding-ifuturet)
80+
- [Key Properties of `IFuture<T>`](#key-properties-of-ifuturet)
81+
- [Key Methods of `IFuture<T>`](#key-methods-of-ifuturet)
82+
- [Example Usage of `IFuture<T>`](#example-usage-of-ifuturet)
8083
- [Understanding `Reference<T>`](#understanding-referencet)
84+
- [Key Properties of `Reference<T>`](#key-properties-of-referencet)
85+
- [Key Methods of `Reference<T>`](#key-methods-of-referencet)
86+
- [Example Usage of `Reference<T>`](#example-usage-of-referencet)
8187
- [Understanding `Future<Reference<T>>`](#understanding-futurereferencet)
88+
- [Why It Is Needed](#why-it-is-needed)
8289

8390
---
8491

@@ -96,7 +103,7 @@ openupm add extensions.unity.imageloader
96103

97104
In the main thread somewhere at the start of the project need to call `ImageLoader.Init();` once to initialize static properties in the right thread. It is required to make in the main thread. Then you can use `ImageLoader` from any thread and at any time.
98105

99-
``` C#
106+
```csharp
100107
ImageLoader.Init(); // just once from the main thread
101108
```
102109

@@ -106,7 +113,7 @@ ImageLoader.Init(); // just once from the main thread
106113
107114
`ImageLoader.LoadSprite` returns `IFuture<Sprite>`. This instance provides all range of callbacks and API to modify it. [Understanding `IFuture<T>`](#understanding-ifuturet).
108115

109-
``` C#
116+
```csharp
110117
ImageLoader.LoadSprite(imageURL) // loading process started
111118
// ┌──────────────────────────┬────────────────────────────────────────────────────────────────────────┐
112119
// │ Loading lifecycle events │ │
@@ -146,7 +153,7 @@ ImageLoader.LoadSprite(imageURL) // loading process started
146153

147154
> [Full sample source code](https://github.com/IvanMurzak/Unity-ImageLoader/blob/master/Assets/_PackageRoot/Samples/SampleLoadSpriteThenSetImage.cs)
148155
149-
``` C#
156+
```csharp
150157
// Load a sprite from the web and cache it for faster loading next time
151158
image.sprite = await ImageLoader.LoadSprite(imageURL);
152159

@@ -158,7 +165,7 @@ await ImageLoader.LoadSprite(imageURL).ThenSet(image);
158165

159166
> [Full sample source code](https://github.com/IvanMurzak/Unity-ImageLoader/blob/master/Assets/_PackageRoot/Samples/SampleLoadTextureThenSetMaterial.cs)
160167
161-
``` C#
168+
```csharp
162169
// Load a Texture2D from the web and cache it for faster loading next time
163170
material.mainTexture = await ImageLoader.LoadTexture(imageURL);
164171

@@ -170,15 +177,15 @@ await ImageLoader.LoadTexture(imageURL).ThenSet(material);
170177

171178
> [Full sample source code](https://github.com/IvanMurzak/Unity-ImageLoader/blob/master/Assets/_PackageRoot/Samples/SampleLoadSpriteThenSetIntoMultipleImages.cs)
172179
173-
``` C#
180+
```csharp
174181
ImageLoader.LoadSprite(imageURL).ThenSet(image1, image2).Forget();
175182
```
176183

177184
## Error handling
178185

179186
> [Full sample source code](https://github.com/IvanMurzak/Unity-ImageLoader/blob/master/Assets/_PackageRoot/Samples/SampleErrorHandle.cs)
180187
181-
``` C#
188+
```csharp
182189
ImageLoader.LoadSprite(imageURL) // Attempt to load a sprite
183190
.ThenSet(image) // If successful, set the sprite to the Image component
184191
.Failed(exception => Debug.LogException(exception)) // If an error occurs, log the exception
@@ -195,7 +202,7 @@ ImageLoader.LoadSprite(imageURL) // Attempt to load a sprite
195202

196203
> [Full sample source code](https://github.com/IvanMurzak/Unity-ImageLoader/blob/master/Assets/_PackageRoot/Samples/SampleAwaitAndForget.cs)
197204
198-
``` C#
205+
```csharp
199206
// Load image and wait
200207
await ImageLoader.LoadSprite(imageURL);
201208

@@ -216,7 +223,7 @@ Cancellation is helpful if target image consumer doesn't exist anymore. For exam
216223
217224
### Cancel by MonoBehaviour events
218225

219-
``` C#
226+
```csharp
220227
ImageLoader.LoadSprite(imageURL)
221228
.ThenSet(image)
222229
.CancelOnEnable(this) // cancel on OnEnable event of current MonoBehaviour
@@ -226,14 +233,14 @@ ImageLoader.LoadSprite(imageURL)
226233

227234
### Explicit cancellation
228235

229-
``` C#
236+
```csharp
230237
var future = ImageLoader.LoadSprite(imageURL).ThenSet(image);
231238
future.Cancel();
232239
```
233240

234241
### Cancellation Token
235242

236-
``` C#
243+
```csharp
237244
var cancellationTokenSource = new CancellationTokenSource();
238245

239246
// loading with attached cancellation token
@@ -244,7 +251,7 @@ ImageLoader.LoadSprite(imageURL, cancellationToken: cancellationTokenSource.Toke
244251
cancellationTokenSource.Cancel(); // canceling
245252
```
246253

247-
``` C#
254+
```csharp
248255
var cancellationTokenSource = new CancellationTokenSource();
249256

250257
ImageLoader.LoadSprite(imageURL)
@@ -257,14 +264,14 @@ cancellationTokenSource.Cancel(); // canceling
257264

258265
### Cancellation by `using`
259266

260-
``` C#
267+
```csharp
261268
using (var future = ImageLoader.LoadSprite(imageURL).ThenSet(image))
262269
{
263270
// future would be canceled and disposed outside of the brackets
264271
}
265272
```
266273

267-
``` C#
274+
```csharp
268275
ImageLoader.LoadSprite(imageURL) // load sprite
269276
.ThenSet(image) // if success set sprite into image
270277
.CancelOnDestroy(this) // cancel OnDestroy event of current gameObject
@@ -293,13 +300,13 @@ Timeout triggers `IFuture<T>` cancellation.
293300
294301
Set global timeout in the settings:
295302

296-
``` C#
303+
```csharp
297304
ImageLoader.settings.timeout = TimeSpan.FromSeconds(30);
298305
```
299306

300307
Set timeout for a specific loading request (`IFuture<T>`):
301308

302-
``` C#
309+
```csharp
303310
ImageLoader.LoadSprite(imageURL) // load sprite
304311
.ThenSet(image) // if success set sprite into image
305312
.Timeout(TimeSpan.FromSeconds(10)) // set timeout duration 10 seconds
@@ -319,15 +326,15 @@ Cache system based on the two layers. The first layer is **Memory cache**, secon
319326

320327
By default it uses `Application.persistentDataPath + "/ImageLoader"`
321328

322-
``` C#
329+
```csharp
323330
ImageLoader.settings.diskSaveLocation = Application.persistentDataPath + "/myCustomFolder";
324331
```
325332

326333
#### Override for a specific loading task
327334

328335
It overrides global `ImageLoader.settings`
329336

330-
``` C#
337+
```csharp
331338
ImageLoader.LoadSprite(url)
332339
.SetUseDiskCache(false)
333340
.SetUseMemoryCache(true);
@@ -337,7 +344,7 @@ ImageLoader.LoadSprite(url)
337344
338345
### Manually read / write into cache
339346

340-
``` C#
347+
```csharp
341348
// Override Memory cache for specific image
342349
ImageLoader.SaveToMemoryCache(url, sprite);
343350

@@ -347,7 +354,7 @@ ImageLoader.LoadSpriteFromMemoryCache(url);
347354

348355
### Check cache existence
349356

350-
``` C#
357+
```csharp
351358
// Check if any cache contains specific image
352359
ImageLoader.CacheContains(url);
353360

@@ -360,7 +367,7 @@ ImageLoader.DiskCacheContains(url);
360367

361368
### Clear cache
362369

363-
``` C#
370+
```csharp
364371
// Clear memory Memory and Disk cache for all images
365372
ImageLoader.ClearCacheAll();
366373

@@ -390,7 +397,7 @@ Texture2D objects consume a lot of memory. Ignoring it may impact performance or
390397

391398
It is simple, just executing this line of code would release memory of a single Texture2D in the case if no other `Reference` pointing on it exists. Before doing that please make sure that no Unity component is using the texture.
392399

393-
``` C#
400+
```csharp
394401
ImageLoader.ClearMemoryCache(url);
395402
```
396403

@@ -402,7 +409,7 @@ Under the hood it calls `UnityEngine.Object.DestroyImmediate(texture)`.
402409

403410
ImageLoader can manager memory releasing of loaded textures. To use it need to call `ImageLoader.LoadSpriteRef` instead of `ImageLoader.LoadSprite`. It returns `Reference<Sprite>` object which contains `Sprite` and `Url`. When `Reference<Sprite>` object is not needed anymore, call `reference.Dispose()` method to release memory, or just don't save the reference on it. It is `IDisposable` and it will be disposed by Garbage Collector. Each new instance of `Reference<Sprite>` increments reference counter of the texture. When the last reference is disposed, the texture memory releases. Also, if any reference is alive, calling `ImageLoader.ClearMemoryCache` or `ImageLoader.ClearCache` would have zero effect for only referenced textures. It prints warning messages about it.
404411

405-
``` C#
412+
```csharp
406413
// Load sprite image and get reference to it
407414
var reference = await ImageLoader.LoadSpriteRef(imageURL);
408415

@@ -424,7 +431,7 @@ reference = null;
424431
425432
`Reference<T>.ThenSet` has a unique feature to attach the reference to the target consumer if consumer is `UnityEngine.Component`. The reference would be disposed as only the consumer gets destroyed.
426433

427-
``` C#
434+
```csharp
428435
ImageLoader.LoadSpriteRef(imageURL) // load sprite using Reference
429436
.ThenSet(image) // if success set sprite into image, also creates binding to `image`
430437
.Forget();
@@ -434,7 +441,7 @@ ImageLoader.LoadSpriteRef(imageURL) // load sprite using Reference
434441

435442
It automatically dispose the reference as only `this.gameObject` gets `OnDestroy` callback.
436443

437-
``` C#
444+
```csharp
438445
ImageLoader.LoadSpriteRef(imageURL) // load sprite using Reference
439446
.Then(reference => reference.DisposeOnDestroy(this))
440447
.Then(reference =>
@@ -447,14 +454,113 @@ ImageLoader.LoadSpriteRef(imageURL) // load sprite using Reference
447454

448455
#### Get references count
449456

450-
``` C#
457+
```csharp
451458
var count = ImageLoader.GetReferenceCount(imageURL); // get count of references
452459
```
453460

461+
---
462+
454463
# Other
455464

456465
## Understanding `IFuture<T>`
457466

467+
The `IFuture<T>` interface represents an asynchronous operation that will eventually produce a result of type `T`. It provides a range of methods and properties to handle the lifecycle of the asynchronous operation, including loading, success, failure, and cancellation events.
468+
469+
### Key Properties of `IFuture<T>`
470+
471+
- **`Id`**: Unique identifier for the future.
472+
- **`Url`**: URL associated with the future.
473+
- **`IsCancelled`**: Indicates if the operation has been cancelled.
474+
- **`IsLoaded`**: Indicates if the operation has successfully loaded the result.
475+
- **`IsCompleted`**: Indicates if the operation has completed (either successfully or with an error).
476+
- **`IsInProgress`**: Indicates if the operation is currently in progress.
477+
- **`Status`**: Current status of the future.
478+
- **`CancellationToken`**: Token used to cancel the operation.
479+
- **`Value`**: The result of the operation.
480+
- **`LogLevel`**: The logging level for the operation.
481+
482+
### Key Methods of `IFuture<T>`
483+
484+
- **``Then(Action<T> onCompleted)``**: Registers a callback to be executed when the operation successfully completes and produces a result.
485+
- **`Failed(Action<Exception> action)`**: Registers a callback to be executed if the operation fails with an exception.
486+
- **`Completed(Action<bool> action)`**: Registers a callback to be executed when the operation completes, regardless of success or failure. The boolean parameter indicates whether the operation was successful.
487+
- **`Canceled(Action action)`**: Registers a callback to be executed if the operation is canceled.
488+
- **`SetUseDiskCache(bool value = true)`**: Configures whether the operation should use disk caching.
489+
- **`SetUseMemoryCache(bool value = true)`**: Configures whether the operation should use memory caching.
490+
- **`SetLogLevel(DebugLevel value)`**: Sets the logging level for the operation.
491+
- **`Cancel()`**: Cancels the operation if it is still in progress.
492+
- **`Forget()`**: Ignores the result of the operation, useful for avoiding compilation warnings about unawaited tasks.
493+
- **`AsUniTask()`**: Converts the `IFuture<T>` instance to a `UniTask<T>`.
494+
- **`AsTask()`**: Converts the `IFuture<T>` instance to a `Task<T>`.
495+
- **`AsReference(DebugLevel logLevel = DebugLevel.Trace)`**: Converts the `IFuture<T>` instance to a `Future<Reference<T>>` instance.
496+
- **`GetAwaiter()`**: Returns an awaiter for the `IFuture<T>` instance, allowing it to be awaited using the `await` keyword.
497+
- **`PassEvents(IFutureInternal<T> to, bool passCancelled = true)`**: Passes events to another future.
498+
- **`PassEvents<T2>(IFutureInternal<T2> to, Func<T, T2> convert, bool passCancelled = true)`**: Passes events to another future with conversion.
499+
- **`Register(CancellationToken cancellationToken)`**: Registers a new cancellation token to cancel the future with it.
500+
- **`Timeout(TimeSpan duration)`**: Sets a timeout duration for the future. If the duration is reached, it fails the future with a related exception.
501+
502+
### Example Usage of `IFuture<T>`
503+
504+
```csharp
505+
ImageLoader.LoadSprite(imageURL) // Start loading the sprite
506+
.Then(sprite => Debug.Log("Loaded")) // On successful load
507+
.Failed(exception => Debug.LogException(exception)) // On failure
508+
.Completed(isLoaded => Debug.Log($"Completed, isLoaded={isLoaded}")) // On completion
509+
.Canceled(() => Debug.Log("Canceled")) // On cancellation
510+
.Forget(); // Avoid compilation warnings
511+
```
512+
458513
## Understanding `Reference<T>`
459514

515+
The `Reference<T>` class is used to manage the lifecycle of loaded resources, such as `Texture2D` or `Sprite`, in a memory-efficient manner. It helps to automatically release memory when the resource is no longer needed, preventing memory leaks and optimizing performance.
516+
517+
### Key Properties of `Reference<T>`
518+
519+
- **`Value`**: The actual resource (e.g., `Sprite` or `Texture2D`) that is being referenced.
520+
- **`Url`**: The URL associated with the resource.
521+
- **`IsDisposed`**: Indicates whether the reference has been disposed.
522+
523+
### Key Methods of `Reference<T>`
524+
525+
- **`Dispose()`**: Disposes the reference, releasing the associated resource from memory. This should be called when the resource is no longer needed.
526+
- **`DisposeOnDestroy(Component component)`**: Automatically disposes the reference when the specified `Component` is destroyed. This is useful for ensuring that resources are released when the associated GameObject is destroyed.
527+
- **`DisposeOnDisable(Component component)`**: Automatically disposes the reference when the specified `Component` is disabled.
528+
- **`DisposeOnEnable(Component component)`**: Automatically disposes the reference when the specified `Component` is enabled.
529+
530+
### Example Usage of `Reference<T>`
531+
532+
```csharp
533+
// Load a sprite using Reference
534+
var reference = await ImageLoader.LoadSpriteRef(imageURL);
535+
536+
// Use the sprite
537+
var sprite = reference.Value;
538+
539+
// Dispose the reference when the sprite is no longer needed
540+
reference.Dispose();
541+
```
542+
543+
```csharp
544+
// Alternatively, automatically dispose the reference when the GameObject is destroyed
545+
ImageLoader.LoadSpriteRef(imageURL)
546+
.Then(reference => reference.DisposeOnDestroy(this))
547+
.Then(reference =>
548+
{
549+
var sprite = reference.Value;
550+
// use sprite
551+
})
552+
.Forget();
553+
```
554+
460555
## Understanding `Future<Reference<T>>`
556+
557+
The `Future<Reference<T>>` class combines the functionality of `IFuture<T>` and `Reference<T>`, providing a powerful tool for managing the lifecycle of asynchronous operations that produce resources such as `Texture2D` or `Sprite`. This combination allows you to handle the loading process and the resource management in a memory-efficient manner.
558+
559+
### Why It Is Needed
560+
561+
The `Future<Reference<T>>` class is needed to ensure that resources are loaded asynchronously and managed efficiently. By using this class, you can:
562+
563+
1. **Load Resources Asynchronously**: Start loading resources such as `Texture2D` or `Sprite` without blocking the main thread.
564+
2. **Manage Resource Lifecycle**: Automatically release resources when they are no longer needed, preventing memory leaks and optimizing performance.
565+
3. **Handle Loading Events**: Register callbacks for various events such as success, failure, and cancellation during the loading process.
566+
4. **Bind Resources to Components**: Automatically dispose of resources when the associated `UnityEngine.Component` is destroyed, ensuring that resources are released when the GameObject is destroyed.

0 commit comments

Comments
 (0)