重新启动应用程序时,来自Xamarin Messaging中心的多条消息

问题描述 投票:4回答:5

我有一个Xamarin Forms应用程序,我使用MessagingCenter将一些数据从特定平台发送到Xamarin.Forms应用程序。

在我的Page中,我订阅了base.OnAppearing()中的消息,并在base.OnDisappearing()方法中取消订阅。这按预期工作。

我遇到的问题是,当应用程序被AndroidOS停止时(例如,当我更改设备的语言时),我开始获取消息的副本。我很困惑为什么会这样,但我注意到重启应用程序时没有调用base.OnDisappearing()方法。

有谁知道什么可能导致我的问题以及如何解决它?另外,Xamarin有什么方法可以看到你所有的发布者和订阅者吗?

c# xamarin xamarin.android xamarin.forms
5个回答
3
投票

像Greensy说的那样,除了订阅OnAppearing()和取消订阅OnDisappearing()之外,我还在订阅之前取消订阅消息,因为,为什么不:

protected override async void OnAppearing() {
    base.OnAppearing();

    MessagingCenter.Unsubscribe<string>(this, "KeyHere");
    MessagingCenter.Subscribe<string>(this, "KeyHere", string => { }));
}

1
投票

在Xamarin.Forms v2.3.4.247中,在Android上,在测试中,我们发现当一个模态页面位于导航页面顶部并且你离开应用程序时,导航页面调用了OnDisappearing()方法,而不是实际上位于顶部的模态页面。为了解决这个问题,我们做了以下工作: - 在OnAppearing方法中,检查你是否真的处于最佳状态 - 如果你处于最佳位置,一切都很好 - 如果你不在最顶层,请自行调用SendDisappearing(),以及SendAppearing ()在实际页面上。我们还发现您需要在页面顶部调用SendDisappearing(),因为Xamarin表单可以保护这些方法免受多次调用。换句话说,如果你两次调用SendDisappearing(),它只会执行一次。

这是一个适合我们的例子,因为我们有一个BaseContentPage,从中派生所有页面:

protected override void OnAppearing()
{
    base.OnAppearing();
    var pageOnTop = ModalContentPageOnTop();
    if (pageOnTop == null || pageOnTop == this)
    {
        // do some stuff, like setting up subscriptions
        SetupSubscriptions();
    }
    else
    {
        // Xamarin Forms Appearing/Disappearing Bug
        // Found that when you leave the Android app with a modal page on top of a non-modal page (either minimise the app or lock the device), then Xamarin.Forms does not properly call OnAppearing. 
        // Xamarin.Forms will call OnAppearing on the non-modal page and not on the modal page. This would not only cause message subscriptions to not be set up on the modal page, 
        // but would also set up message subscriptions on the non-modal page. Not good.  Hopefully, this work-around should stop being executed when Xamarin fixes the problem, as we won't 
        // fall into this "else" condition above, because OnAppearing will be called on the right page.

        // NOTE: SendDisappearing and SendAppearing have boolean guards on them. If SendAppearing was called last, calling it again will do nothing.
        // SendDisappearing has the same behaviour. Thus we need to call SendDisappearing first, to be guaranteed that SendAppearing will cause the OnAppearing() method to execute.
        ((IPageController)pageOnTop).SendDisappearing();  // try and correct Xamarin.Forms - the page actually on top was not told it was disappearing - tell it now
        ((IPageController)this).SendDisappearing();  // try and correct Xamarin.Forms - if it thinks the view has appeared when it hasn't, it won't call OnAppearing when it is truly appearing.
        ((IPageController)pageOnTop).SendAppearing();  // try and correct Xamarin.Forms by notifying the correct page that it is appearing
    }
}

ModalContentPageOnTop的样子:

private ContentPage ModalContentPageOnTop()
{
    var page = Navigation.ModalStack.LastOrDefault();
    var navigationPage = page as NavigationPage;
    if (navigationPage != null)
        return navigationPage.CurrentPage as ContentPage;
    return page as ContentPage;
}

我们的应用程序中有一个非常浅的导航层次结构,因此这种方法可能无法用于更复杂的导航堆栈(即推送其他页面或其他模态页面的模态页面)


0
投票

我通过做这样的事情解决了我的问题 -

MessagingCenter.Subscribe<string, DetailClass>(this, "KeyHere", async (detail) =>  
{
   // do someting....
   MessagingCenter.Unsubscribe<string,DetailClass>(this, "KeyHere");
});

在订阅方法中取消订阅消息中心。


0
投票

您可以在页面构造函数中的OnAppearing之后订阅它并取消订阅,而不是使用OnDisappearingInitializeComponent()

protected override void OnParentSet()
{
    base.OnParentSet();

    if (Parent == null)
    {
        // unsubscribe 
    }
}

OnParentSetOnAppearing之前和OnDisappearing之后被召唤。但是,在从导航堆栈中删除页面或弹出页面时,Parent仅在页面上变为空。这确保它们都只被调用一次,而我注意到OnAppearingOnDisappearing并不总是被一致地调用,这取决于弹出窗口和/或其他东西的显示方式。


0
投票

问题结果与Xamarin.Forms没有直接关系,但是由于在我的BroadcastReceiever类中的OnStop方法中没有正确注销MainActivity的问题。因此,每当应用程序通过OnStop/OnStart循环时,即使我只有一个有效订阅,也会发送2条消息。

我还在我的Unsubsribe方法中使用Xamarin.Forms ContentPages调用OnDisappearing,并在Unsubscribe方法中调用Subscribe之前调用OnAppearing

到目前为止,我还没有在任何设备或不同的Android版本上再次遇到此问题。

还有一些额外的建议,不要忘记取消订阅你在OnDisappearing方法中剩余的MessagingCenter订阅,否则你会遇到一些奇怪的错误,这会让你的头发变成灰色。有一篇关于这个主题的好文章,但我再也找不到了。

© www.soinside.com 2019 - 2024. All rights reserved.