mercredi 20 juillet 2022

Singleton pattern doesn't work in Xamarin multi-platform project MVVM

I have a C# (Xamarin) solution structured like this:

πŸ“¦ Solution
 ┣ πŸ“‚ Main application
 ┃ ┣ πŸ“‚ ViewModel Project
 ┃ ┃ ┣ πŸ“œ ...
 ┃ ┣ πŸ“‚ Android Project
 ┃ ┃ ┣ πŸ“œ MyActivity.cs
 ┃ ┃ ┣ πŸ“œ ...
 ┃ ┣ πŸ“‚ iOS Project
 ┃ ┃ ┣ πŸ“œ ...
 ┗ πŸ“‚ Multiplaftorm Library
   ┣ πŸ“‚ Android-specific Library Project
   ┃ ┣ πŸ“œ MyModuleAndroid.cs
   ┃ ┣ πŸ“œ ...
   ┣ πŸ“‚ iOS-specific Library Project
   ┃ ┣ πŸ“œ MyModuleiOS.cs
   ┃ ┣ πŸ“œ ...
   ┣ πŸ“‚ Shared Library Project (.shproj)
   ┃ ┣ πŸ“œ MyLibrary.Shared.projitems
   ┃ ┣ πŸ“œ Service.cs
   ┃ ┣ πŸ“œ Factory.cs
   ┃ ┣ πŸ“œ IMyModule.cs
   ┃ ┣ πŸ“œ ...

The module requires very device specific initialization, that I must do in the platform specific part (I make the example with Android)

// MyActivity.cs

[Activity(Label = "", WindowSoftInputMode = SoftInput.AdjustPan]
public class MyActivity
{   
    protected override void OnCreate(Bundle savedInstanceState)
    {
        MyModuleAndroid.Init(this); // I need an Activity as input
    }

...

The Init involves a singleton pattern:

// MyModuleAndroid.cs

public class MyModuleAndroid
{
    public static void Init(Activity activity)
    {
        Factory.GetInstance().DoSomething();
    }
}
// Factory.cs

public class Factory
{
    private static Factory instance;

    public static Factory GetInstance()
    {
        if (instance == null)
        {
            // only if no instance existing, I create a new one
            instance = new NFCModuleFactory();
        }

        return instance;
    }
...
}

Then, the instance is used inside the Service (shared project) that is called always from view model. But... here is the problem: the first time I try to access the instance (the second, after the initialization), I found it's null, so the singleton re-creates a new instance! If I call again from service the instance is mantained, but I already lost all my initalization data.

How can I solve this?

As a workaround, I noticed that If I structure my library like this, so by creating a fourth project that manages the factory (so the singleton), it works perfectly:

 ┗ πŸ“‚ Multiplaftorm Library
   ┣ πŸ“‚ Android-specific Library Project
   ┃ ┣ πŸ“œ MyModuleAndroid.cs
   ┃ ┣ πŸ“œ ...
   ┣ πŸ“‚ iOS-specific Library Project
   ┃ ┣ πŸ“œ MyModuleiOS.cs
   ┃ ┣ πŸ“œ ...
   ┣ πŸ“‚ Shared Library Project (.shproj)
   ┃ ┣ πŸ“œ MyLibrary.Shared.projitems
   ┃ ┣ πŸ“œ Service.cs
   ┣ πŸ“‚ Standard Project (.csproj)
   ┃ ┣ πŸ“œ Factory.cs
   ┃ ┣ πŸ“œ IMyModule.cs
   ┃ ┣ πŸ“œ ...

As I said, in this way it works... but I really cannot understand why! :-(

Aucun commentaire:

Enregistrer un commentaire