How can I stop a Device.StartTimer () when I change the page and when my app is moved to the backgro

I'm trying to create a ListView which refreshes its content every 5 seconds, for this I'm using a Device.StartTimer (), I've managed to make it work, but I've noticed that Device.StartTimer () is global to the application and what put in the callback is still running even when I change the page or change the application on my device.

My question is: How can I get the timer to stop when I change the page and change the application?

So far I have had some progress, which is that using OnAppearing, OnDisAppearing and the MessagingCenter I have managed to change the page when the timer stops.

With this implementation, I am worried that I really do not know if I am really unsubscribing from the message, it is the right place, I would like someone to tell me about it too.

Below fragments of my View and my ViewModel:

View:

public partial class MonitoringView : TabbedPage
{

    MonitoringViewModel context = new MonitoringViewModel();

    public MonitoringView()
    {
        InitializeComponent();
        BindingContext = context;
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        MessagingCenter.Send<MonitoringView>(this, "OnAppearing");
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();
        MessagingCenter.Send<MonitoringView>(this, "OnDisAppearing");
    }
}

ViewModel:

public class MonitoringTabsViewModel : Notificable
{
    public string IdCode { get; set; }

    public bool InPage { get; set; }

    private string description;

    public string Description
    {
        get { return description; }
        set
        {
            description = value;
            OnPropertyChanged();
        }
    }

    private ObservableCollection<PcData> sensors;

    public ObservableCollection<PcData> Sensors
    {
        get { return sensors; }
        set
        {
            sensors = value;
            OnPropertyChanged();
        }
    }


    public MonitoringTabsViewModel(string idCode, string description)
    {
        IdCode = idCode;
        Description = description;
        LoadSensors(idCode);
        MessagingCenter.Subscribe<MonitoringView>(this, "OnAppearing", (sender) =>
        {
            InPage = true;
        });
        MessagingCenter.Subscribe<MonitoringView>(this, "OnDisAppearing", (sender) =>
        {
            InPage = false;
        });
        Device.StartTimer(TimeSpan.FromSeconds(5), TimerCallBack);
    }

    private bool TimerCallBack()
    {
        if (InPage)
        {
            RefreshSensors(IdCode);
            MessagingCenter.Unsubscribe<MonitoringView>(this, "OnAppearing");
            return true;
        }
        else
        {
            MessagingCenter.Unsubscribe<MonitoringView>(this, "OnDisAppearing");
            return false;
        }
    }

    private async void LoadSensors(string idCode)
    {
        Sensors = new ObservableCollection<PcData>(await App.WebApiManager.GetCurrentStatusDeviceAsync(idCode));
    }

    private async void RefreshSensors(string idCode)
    {
        Sensors = null;
        Sensors = new ObservableCollection<PcData>(await App.WebApiManager.GetCurrentStatusDeviceAsync(idCode));
    }
}

Answers

  • jezhjezh Member, Xamarin Team Xamurai

    When you put the following code inside of public partial class MonitoringView : TabbedPage

       protected override void OnDisappearing()
      {
        base.OnDisappearing();
        MessagingCenter.Send<MonitoringView>(this, "OnDisAppearing");
       }
    

    The method: protected override void OnDisappearing() is not always fired, so
    the code: MessagingCenter.Send(this, "OnDisAppearing"); will not be called.

    You can try to do this in the child page of MonitoringView.

Sign In or Register to comment.