Show loading if data is loading

By monitoring the events from the Fetch Data, I can determine when the data is in the process of loading and when it's not. Utilizing these events, I display the loading status as follows:

In simple terms, I verify if the data is loading and then initiate a loading process using the Memory Pool of FSLoading. Here's how it works:

/// <summary>
/// Pool for the loading
/// </summary>
public class FSLoadingPool
{
    private FSLoading.Pool _pool;

    /// <summary>
    /// Constructor and Memory Pool is passed as an argument to cache
    /// </summary>
    /// <param name="pool">Pool to use</param>
    public FSLoadingPool(FSLoading.Pool pool)
    {
        _pool = pool;
    }

    /// <summary>
    /// Calls when need to spawn FS Loading
    /// </summary>
    /// <param name="parent">what is the parent of this UI element</param>
    /// <returns>the reference of the loading</returns>
    public FSLoading Spawn(Transform parent)
    {
        return _pool.Spawn(parent);
    }

    /// <summary>
    /// Calls when need to remove or despawn
    /// </summary>
    /// <param name="loading">item to despawn</param>
    public void Remove(FSLoading loading)
    {
        _pool.Despawn(loading);
    }
}

This refers to the loading pool. I've attached a script to the loading prefabs, which serves to provide a UI reference and update the UI based on the data. The parent of the Loading is passed as an argument during the spawn process, as shown below:

/// <summary>
/// Class component attach to the prefab of loading
/// </summary>
public class FSLoading : MonoBehaviour
{
    /// <summary>
    /// Text to show on the loading
    /// </summary>
    [SerializeField]
    private TextMeshProUGUI _title;
    /// <summary>
    /// % of loading done in this process
    /// </summary>
    [SerializeField]
    private TextMeshProUGUI _progress;

    /// <summary>
    /// The image fillamount on the loading
    /// </summary>
    [SerializeField]
    private Image _fill;

    /// <summary>
    /// Calls when the loading prefab is spawned
    /// </summary>
    /// <param name="parent">parent to be of this object</param>
    public void Setup(Transform parent)
    {
        RectTransform transform = GetComponent<RectTransform>();
        transform.parent = parent;
        transform.localPosition = Vector3.zero;
        transform.offsetMin = Vector2.zero;
        transform.offsetMax = Vector2.zero;
    }

    /// <summary>
    /// Calls when need to update the loading
    /// </summary>
    /// <param name="progress">value of the progress from 0 - 1</param>
    /// <param name="info">text information of the loading / like what is loading can be different text</param>
    public void ShowProgress(float progress, string info)
    {
        _fill.fillAmount = progress;
        _progress.text = string.Format("{0} %", (int)(progress * 100.00));
        _title.text = info;
    }

    /// <summary>
    /// Pool of the Loading
    /// </summary>
    public class Pool : MonoMemoryPool<Transform, FSLoading>
    {
        /// <summary>
        /// Calls on the initialize of the item initialize
        /// </summary>
        /// <param name="p1">parent to be</param>
        /// <param name="item">item spawned</param>
        protected override void Reinitialize(Transform p1, FSLoading item)
        {
            base.Reinitialize(p1, item);
            item.Setup(p1);
        }
    }
}

Following that, I generate a few instances in the pool using the Zenject code, as shown below:

/// <summary>
/// Zenject Installer attach to the scene context
/// </summary>
public class FSLoadingInstaller : MonoInstaller
{
    /// <summary>
    /// Loading to spawn
    /// </summary>
    public GameObject _loader;

    public override void InstallBindings()
    {
        // binding the pool
        Container.Bind<FSLoadingPool>().AsSingle();
        // spawning item from the pool
        Container.BindMemoryPool<FSLoading, FSLoading.Pool>().WithInitialSize(1).FromComponentInNewPrefab(_loader).UnderTransformGroup("FSLoading");
    }
}

The memory pool has been prepared and is now available. I can initiate it as required in the following manner:

_loaderPool.Spawn(loaderParent);

The complete script is now configured for retrieval as shown below:

/// <summary>
/// Attach on the parent of the event
/// </summary>
public class EventDataUI : MonoBehaviour
{
    /// <summary>
    /// Data to load from the URL
    /// </summary>
    [SerializeField]
    private string url = "https://script.google.com/macros/s/AKfycbxHLP8yjErEQhU-BLTMJE6i0MllRpEPF2qTcVx0xNoe7Ur34dPqIG8bh4ay3CwUoQL4/exec";

    /// <summary>
    /// Fetch Data of the Event Injected object
    /// </summary>
    [Inject]
    private IFetchData<List<EventsData>> _fetchData;
    /// <summary>
    /// Pool of the loading
    /// </summary>
    [Inject]
    private FSLoadingPool _loaderPool;

    /// <summary>
    /// Cache the event data in this variable
    /// </summary>
    [SerializeField]
    private List<EventsData> _eventsData;

    /// <summary>
    /// FS loading parent
    /// </summary>
    [SerializeField]
    private Transform loaderParent;

    /// <summary>
    /// Spawned FSLoader reference
    /// </summary>
    private FSLoading loader;
    /// <summary>
    /// Loading status of the data
    /// </summary>
    private LoadingStatus _loadStatus;
    /// <summary>
    /// Message to show on the FS Loading
    /// </summary>
    private string _message = "Loading Events Data.";

    private void Awake()
    {
        // Fetch Data and wait till it's downloaded
        StartCoroutine(_fetchData.FetchData(url, OnProgress, OnCompleted));
    }

    private void OnEnable()
    {
        // Update load status
        if (_loadStatus == LoadingStatus.InProgress)
        {
            loader = _loaderPool.Spawn(loaderParent);
            // Update message while loading
            DOTween.To(() => _message, x => _message = x, _message + "...", 2).SetLoops(10);
        }
    }

    /// <summary>
    /// Calls when the data loading is in progress
    /// </summary>
    /// <param name="progress">progress of the laoding 0 - 1</param>
    /// <param name="info">message to display on the progress</param>
    void OnProgress(float progress, string info)
    {
        _loadStatus = LoadingStatus.InProgress;
        if (loader)
            loader.ShowProgress(progress, _message);
    }

    /// <summary>
    /// Calls when data is laoded
    /// </summary>
    /// <param name="isDone">is it completed or fail</param>
    /// <param name="data">output data</param>
    void OnCompleted(bool isDone, List<EventsData> data)
    {
        _loadStatus = isDone ? LoadingStatus.Completed : LoadingStatus.Fail;

        if (!isDone)
            return;

        _eventsData = data;
        // order downloaded data by the event type
        // active at top, coming soon at second and expired at below
        _eventsData = _eventsData.OrderBy(x => (int)x.EventType).ToList();
        // run for every item
        _eventsData.ForEach(item =>
        {
            // initialize item
            item.Init();
            // spawn items prefab here
        });

        if (loader)
            _loaderPool.Remove(loader);
    }
}

Last updated