DataLoader

Helper class to simplify loading and caching data. Intended to use with ListView items to avoid problems with reusable instances.

Usage

public class ListViewImage : ListViewCustom<ImageItem, string>
{
        public DataLoader<string, Sprite> Loader;

        protected override void InitOnce()
        {
                base.InitOnce();

                Loader = new DataLoader<string, Sprite>(async request =>
                {
                        var web_request = UnityWebRequest.Get(request);

                        await web_request.SendWebRequest();

                        if (web_request.result != UnityWebRequest.Result.Success)
                        {
                                Debug.LogWarning(string.Format("UnityWebRequest Failed. URI: {0}; Result: {1}; Code: {2}; Content: {3}",
                                        request, web_request.result, web_request.responseCode, web_request.downloadHandler.text));
                                return new Tuple<bool, Sprite>(false, null);
                        }

                        var texture = DownloadHandlerTexture.GetContent(web_request);
                        var sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
                        return new Tuple<bool, Sprite>(true, sprite);
                });
        }
}

public class ImageItem : ListViewItem, IViewData<string>
{
        public Image Image;

        protected string Item;

        protected DataLoader<string, Sprite> Loader => (Owner as ListViewImage).Loader;

        public void SetData(string item)
        {
                Item = item;
                UpdateView(item);
        }

        async void UpdateView(string url)
        {
                // reset image or show "loading" placeholder
                Image.sprite = null;

                // load sprite
                var (success, sprite) = await Loader.GetAsync(url);

                // if sprite was not loaded
                if (!success)
                {
                        return;
                }

                // check if item is still same (item will be different if ImageItem instance was recycled)
                if (Item != url)
                {
                        // do nothing
                        return;
                }

                Image.sprite = sprite;
        }