es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Xamarin ¿Qué sucede con el singleton inicializado de manera perezosa después de que la aplicación se va al segundo plano?

Uso de inicialización diferida para singleton de aplicación en Xamarin.Forms (la aplicación se ejecuta en iOS):

public sealed class DataSingleton
{
    private static readonly Lazy<datasingleton> lazy = new Lazy<datasingleton>(() => new DataSingleton(), LazyThreadSafetyMode.PublicationOnly); // también intenté sin el segundo parámetro

    public static DataSingleton Instance
    {
        get { return lazy.Value; }
    }
    ...
}

Y lo llamo en el servidor web que se ejecuta para proporcionar datos al front-end que está en Angular (uso una vista web para mostrar el código de Angular):

var server = new WebServer(o => o
        .WithUrlPrefix($"http://localhost:{appSettings.ApiPort}")
        .WithMode(HttpListenerMode.EmbedIO))
    .WithCors()
    .WithLocalSessionManager()
    .WithWebApi("/api", m => m
        .WithController<testcontroller>()
        .WithController<settingscontroller>()
        .WithController<reportcontroller>()
        .WithController<systemcontroller>())
    .WithModule(new ActionModule("/", HttpVerbs.Any,
        ctx => ctx.SendDataAsync(new { Message = "Error" })))
    .RunAsync();

En los controladores se llama a DataSingleton para obtener/establecer datos, pero después de que la aplicación vuelva del segundo plano, DataSingleton.Instance es nulo.

¿Qué debo hacer para no perder los datos del singleton mientras la aplicación está en segundo plano durante poco tiempo (aproximadamente 5 minutos)?

Actualización: Me he dado cuenta de que este problema solo ocurre en los controladores, porque cuando la aplicación vuelve a primer plano, puedo ver todos los datos en el evento WillEnterForeground de AppDelegate.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para evitar perder datos de un singleton cuando la aplicación está en segundo plano durante un corto período de tiempo, puedes utilizar los eventos del ciclo de vida de la aplicación en Xamarin.iOS para persistir y restaurar el objeto singleton.

    Primero, puedes agregar controladores de eventos para los eventos DidEnterBackground y WillEnterForeground en tu clase AppDelegate:

    public override void DidEnterBackground(UIApplication application)
    {
        // Persistir los datos del singleton aquí, por ejemplo, utilizando NSUserDefaults o una base de datos SQLite
    }
    
    public override void WillEnterForeground(UIApplication application)
    {
        // Restaurar los datos del singleton aquí
    }
    

    En el controlador de eventos DidEnterBackground, puedes guardar los datos relevantes del objeto singleton en un almacenamiento persistente, como NSUserDefaults o una base de datos SQLite. Luego, en el controlador de eventos WillEnterForeground, puedes restaurar los datos desde el almacenamiento hacia el objeto singleton.

    Alternativamente, si solo necesitas persistir el objeto singleton temporalmente (es decir, durante el tiempo en que la aplicación está en segundo plano), puedes serializar el objeto en un arreglo de bytes y guardarlo en NSUserDefaults utilizando NSData:

    public override void DidEnterBackground(UIApplication application)
    {
        var binaryFormatter = new BinaryFormatter();
        using (var stream = new MemoryStream())
        {
            binaryFormatter.Serialize(stream, DataSingleton.Instance);
            var data = NSData.FromArray(stream.ToArray());
            NSUserDefaults.StandardUserDefaults.SetValueForKey(data, new NSString("DataSingleton"));
        }
    }
    
    public override void WillEnterForeground(UIApplication application)
    {
        var data = NSUserDefaults.StandardUserDefaults.ValueForKey(new NSString("DataSingleton")) as NSData;
        if (data != null)
        {
            var binaryFormatter = new BinaryFormatter();
            using (var stream = new MemoryStream(data.ToArray()))
            {
                DataSingleton.Instance = (DataSingleton)binaryFormatter.Deserialize(stream);
            }
        }
    }
    

    Ten en cuenta que en este ejemplo, DataSingleton necesita ser serializable (es decir, marcado con el atributo [Serializable]). Además, la clase DataSingleton necesita tener un constructor por defecto (es decir, un constructor sin parámetros) para que la deserialización funcione.

Comments are closed.