Show loading if data is loading
Last updated
Last updated
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);
}
}