f-miyu / Plugin.CloudFirestore

MIT License
121 stars 44 forks source link

Remove AddSnapshotListener #64

Closed angelru closed 3 years ago

angelru commented 3 years ago

Is there any way that when the application is closed all the AddSnapshotListeners are removed? I am making a chat application and I would like to implement this. Currently when the user does a gobackpage I remove it: chatMessagesListener.Remove (); but if you close the app this does not happen.

f-miyu commented 3 years ago

I think AddSnapshotListeners is not needed to be removed when the application is closed. Please tell me more about your problem and show me your code if possible.

f-miyu commented 3 years ago

I think the listener should be removed before the application go to background. If you use Prism, you can use IApplicationLifecycleAware. Remove the listener in OnSleep() and Add in OnResume(). Otherwise, you can do the same thing with OnSleep and OnResume method of Xamarin.Forms.Application class.

For example:

public class ViewModel : BindableBase, IApplicationLifecycleAware
{
    private IListenerRegistration listener;

    public ViewModel()
    {
        AddSnapshotListener();
    }

    public void OnResume()
    {
        if (listener == null)
        {
            AddSnapshotListener();
        }
    }

    public void OnSleep()
    {
        listener?.Remove();
        listener = null;
    }

    private void AddSnapshotListener()
    {
        listener = CrossCloudFirestore.Current.Instance
            .GetCollection("collection")
            .AddSnapshotListener(snapshot, error) =>
            {
            });
    }
}
angelru commented 3 years ago

yes, i thought so too, but in this project i don't use prism since i'm using shell. I think it is a bit cumbersome to go through each viewmodel removing the listener (since I have several, but I imagine there will be no other alternatives)

f-miyu commented 3 years ago

I think you should use MessagingCenter in order to notify the ViewModel of OnSleep or OnResume.

public partial class App : Application
{
    public App()
    {
        InitializeComponent();

        MainPage = new MainPage();
    }

    protected override void OnSleep()
    {
        MessagingCenter.Instance.Send(this, "OnSleep");
    }

    protected override void OnResume()
    {
        MessagingCenter.Instance.Send(this, "OnResume");
    }
}
public class ViewModel
{
    private IListenerRegistration listener;

    public ViewModel()
    {
        AddSnapshotListener();

        MessagingCenter.Instance.Unsubscribe<App>(MessagingCenter.Instance, "OnResume");
        MessagingCenter.Instance.Unsubscribe<App>(MessagingCenter.Instance, "OnSleep");

        MessagingCenter.Instance.Subscribe<App>(MessagingCenter.Instance, "OnResume",  OnResume);
        MessagingCenter.Instance.Subscribe<App>(MessagingCenter.Instance, "OnSleep",  OnSleep);
    }

   private void OnResume(App app)
    {
        if (listener == null)
        {
            AddSnapshotListener();
        }
    }

    private void OnSleep(App app)
    {
        listener?.Remove();
        listener = null;
    }

    private void AddSnapshotListener()
    {
        listener = CrossCloudFirestore.Current.Instance
            .GetCollection("collection")
            .AddSnapshotListener(snapshot, error) =>
            {
            });
    }
}
angelru commented 3 years ago

I thought about MessagingCenter but ended up implementing this, on Android it works fine, I couldn't test on iOS:

     public interface IApplicationLifecycle
     {
         void OnSleep ();
         void OnResume ();
     }
public class ViewModel : BaseViewModel, IApplicationLifecycle
{
        public void OnSleep()
        {

        }

        public void OnResume()
        {

        }
}

App.cs:

        protected override void OnSleep()
        {
            ((Shell.Current?.CurrentItem?.CurrentItem as IShellSectionController)?.PresentedPage
                    .BindingContext as IApplicationLifecycle)?.OnSleep();
        }

        protected override void OnResume()
        {
            ((Shell.Current?.CurrentItem?.CurrentItem as IShellSectionController)?.PresentedPage
                   .BindingContext as IApplicationLifecycle)?.OnResume();
        }