首页 > 解决方案 > 当我更改页面以及将我的应用程序移至后台时,如何停止 Device.StartTimer ()?并正确使用 MessagingCenter

问题描述

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

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

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

有了这个实现,我担心我真的不知道我是否真的退订了消息,这是正确的地方,我也希望有人告诉我。

下面是我的视图和视图模型的片段:

看法:

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

视图模型:

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

标签: c#androidxamarinxamarin.formstimer

解决方案


解决方案:

有了这个实现,我担心我真的不知道我是否真的退订了消息

为了测试您是否真的取消订阅了该消息,您可以在调试与 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停止。


推荐阅读