更改页面以及将应用程序移至后台时如何停止Device.StartTimer()?和正确使用MessagingCenter

时间:2018-11-30 19:19:48

标签: c# android xamarin xamarin.forms timer

我正在尝试创建一个ListView,它每5秒刷新一次其内容,为此,我正在使用Device.StartTimer(),我设法使其工作,但是我注意到Device.StartTimer ()对于应用程序是全局的,即使我更改页面或更改设备上的应用程序,回调中的内容仍在运行。

我的问题是:更改页面和更改应用程序时如何使计时器停止计时?

到目前为止,我已经取得了一些进展,那就是使用OnAppearing,OnDisAppearing和MessagingCenter,我设法在计时器停止时更改了页面。

使用此实现,我担心我真的不知道我是否真的取消订阅该消息,这是正确的位置,我也希望有人也告诉我。

以下是我的View和ViewModel的片段:

查看:

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));
    }
}

1 个答案:

答案 0 :(得分:0)

解决方案:

  

使用此实现,我担心我真的不知道自己是否   真的取消订阅了邮件

要测试您是否确实已取消订阅消息,可以在调试与VS连接的应用程序时将breakpoint添加到RefreshSensors函数中。

然后,您可以在离开MessagingCenter.Send<MonitoringView>(this, "OnAppearing");来查看MonitoringView是否被触发后,在另一页中发送与breakpoint相同的消息,如果没有触发,则表示您已取消订阅从消息中成功。

在您的TimerCallBack代码中,我想您should not在此处取消订阅该消息。当您从其他页面退回时,您将永远不会收到该消息,因为您已取消订阅它们。您可以在此页面为onDestory时退订该消息。

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

此外,您应该在Device.StartTimer(TimeSpan.FromSeconds(5), TimerCallBack);消息中放入onappearing

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

    });
    MessagingCenter.Subscribe<MonitoringView>(this, "OnDisAppearing", (sender) =>
    {
        InPage = false;
    });
}

一旦收到OnAppearing消息,Device.StartTimer将在页面中运行,一旦收到OnDisAppearing消息,回调将返回false并且Device.StartTimer将停止。