Daddoon / BlazorMobile

Create full C# driven hybrid-apps for iOS, Android, UWP & Desktop with Blazor!
MIT License
413 stars 55 forks source link

[question] BlazorMobileService.OnBlazorMobileLoaded event when gets fires? before or after render? #225

Closed arivera12 closed 4 years ago

arivera12 commented 4 years ago

I am needing BlazorDevice.RuntimePlatform to know if I load some data from device storage or browser storage.

I am making huge refactor and I need to now when does this even gets exactly fired?

1) Before Render? 2) After Render?

if it's before render I am ok with that because what I need, needs to be done before render!

if it's after render then I need to workaround because I need to re render the entire application.

Daddoon commented 4 years ago

If you are going the per platform basis by using a Razor Class Library for your Blazor app instead, you will not need to check this kind of value, as per nature you will know from which base app you are actually booting.

But by the way, if you want to use this without slicing your app as per platform basis, BlazorDevice.RuntimePlatform will be not be specifically set until the OnBlazorMobileLoaded is fired in your class inheriting from App.razor, in the sample, MobileApp.cs

See this file.

using BlazorMobile.Common.Components;
using BlazorMobile.Common.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlazorMobile.InteropBlazorApp
{
    public class MobileApp : App
    {
        public MobileApp() : base()
        {
            //In the first sequence we must only load BlazorMobile component
            //When BlazorMobile will be ready, we will render the app
            BlazorMobileService.OnBlazorMobileLoaded += BlazorMobileService_OnBlazorMobileLoaded;
        }

        private void BlazorMobileService_OnBlazorMobileLoaded(object source, BlazorMobileOnFinishEventArgs args)
        {
            //InvokeAsync is mainly needed for .NET Core implementation that need the renderer context
            InvokeAsync(() =>
            {
                //BlazorMobile is ready. We should call StateHasChanged method in order to call BuildRenderTree again.
                //This time, it should load your app with base.BuildRenderTree() method call.
                BlazorMobileService.HideElementById("placeholder");
                StateHasChanged();
            });
        }

        protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
            builder.OpenElement(0, nameof(BlazorMobileComponent));
            builder.OpenComponent(1, typeof(BlazorMobileComponent));
            builder.CloseComponent();
            builder.CloseElement();

            Console.WriteLine($"{nameof(BlazorMobileService.IsBlazorMobileLoaded)}: {BlazorMobileService.IsBlazorMobileLoaded}");
            if (BlazorMobileService.IsBlazorMobileLoaded)
            {
                base.BuildRenderTree(builder);
            }
        }
    }
}

If you see the logic, the registered event will call base.BuildRenderTree(builder) when BlazorMobile finished its initialization routine (by forcing and rechecking thanks to a StateHasChanged call), and so, only then your app render tree is at last loaded.

So we can say that this is Before render, as you have the control over the rendering pipeline with BlazorMobile here.

arivera12 commented 4 years ago

So to see if I understand correctly this logic of extra initialiation I need to do needs to be added inside the InvokeAsync? and StateHasChanged() obviously will re render the entire application.

arivera12 commented 4 years ago

Can this be done actually over here on the program.cs like this.

BlazorMobileService.OnBlazorMobileLoaded += (object source, BlazorMobileOnFinishEventArgs eventArgs) =>
{
    new Action(async () => await InitializeLanguageLocale()).Invoke();
};
arivera12 commented 4 years ago

As far I can see I can see yes it is

Daddoon commented 4 years ago

If you see the code i posted, your app will not render until the first call to the base.BuildRenderTree so there will be not kind of reload effect as your user code is not yet loaded.

And yes, you can add whatever event you want with your logic it is fine ! Just keep the default one to render your app.

arivera12 commented 4 years ago

Thanks again!