You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin Android:Firebase前台通知接收后页面图标不显示问题求助

问题描述

开发Xamarin跨平台应用的Android端,使用FirebasePushNotification Plugin v3.4.35。已按插件要求创建MainApplication类处理通知回调,在OnCreate方法中注册了CrossFirebasePushNotification.Current.OnNotificationReceived事件处理程序,应用处于前台时该事件可正常触发并捕获通知。

主页面OverViewPage中有一个ImageButton,其IsVisible属性绑定到所有ViewModel继承的BaseViewModel中的HaveNotification布尔属性。当OnNotificationReceived事件触发时,实例化新的BaseViewModel并设置HaveNotification=true,但页面图标未响应属性变化显示。询问是否是设置属性的位置导致问题,以及如何让图标在事件触发时显示。


相关代码

MainApplication类

public class MainApplication : Application
{
    public MainApplication(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer) 
    {
    }

    public override void OnCreate()
    {
        base.OnCreate();
        //... 移除无关代码
        CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
        {
            System.Diagnostics.Debug.WriteLine("Received");

            BaseViewModel baseviewmodel = new BaseViewModel
            {
                HaveNotification = true
            };
        };
    }
}

BaseViewModel类

public class BaseViewModel : INotifyPropertyChanged
{
    bool haveNotification = false;
    public bool HaveNotification
    {
        get { return haveNotification; }
        set { SetProperty(ref haveNotification, value); }
    }

    protected bool SetProperty<T>(ref T backingStore, T value,
        [CallerMemberName] string propertyName = "",
        Action onChanged = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingStore, value))
            return false;

        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        var changed = PropertyChanged;
        if (changed == null)
            return;

        changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

OverViewPage布局

<StackLayout Orientation="Horizontal" Margin="0,0,0,0" WidthRequest="250" BackgroundColor="{StaticResource Primary }">
    <ImageButton x:Name="ibtnNotify" IsVisible="{Binding HaveNotification}" Source="@drawable/icon_msg.png"  BackgroundColor="Yellow" HorizontalOptions="End"/>
</StackLayout>

问题分析与解决方案

问题根源

  1. ViewModel实例不匹配:你在通知回调中新建的BaseViewModel是一个独立实例,和OverViewPage绑定的ViewModel不是同一个对象。修改新实例的属性不会触发页面绑定的更新,因为页面监听的是自身绑定的ViewModel的PropertyChanged事件。
  2. 线程问题:Firebase的通知回调可能运行在非UI线程,直接修改绑定属性可能导致UI更新失败或异常。

解决方法

方法1:修改页面绑定的实际ViewModel实例

直接找到OverViewPage当前绑定的ViewModel并更新属性,记得切换到主线程操作:

CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
{
    System.Diagnostics.Debug.WriteLine("Received");
    // 切换到UI线程执行属性更新
    Device.BeginInvokeOnMainThread(() =>
    {
        if (Application.Current.MainPage is OverViewPage mainPage)
        {
            if (mainPage.BindingContext is BaseViewModel vm)
            {
                vm.HaveNotification = true;
            }
        }
    });
};

方法2:使用全局状态管理(更推荐)

创建全局单例的通知状态类,避免页面耦合,同时支持多页面共享状态:

  1. 定义全局状态类
public class NotificationState : INotifyPropertyChanged
{
    private static NotificationState _instance;
    public static NotificationState Instance => _instance ??= new NotificationState();

    private bool _haveNotification;
    public bool HaveNotification
    {
        get => _haveNotification;
        set
        {
            if (_haveNotification != value)
            {
                _haveNotification = value;
                OnPropertyChanged();
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
  1. 修改页面绑定到全局单例
<ImageButton IsVisible="{Binding Source={x:Static local:NotificationState.Instance}, Path=HaveNotification}" 
             Source="@drawable/icon_msg.png"  
             BackgroundColor="Yellow" 
             HorizontalOptions="End"/>
  1. 在通知回调中更新全局状态
CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
{
    System.Diagnostics.Debug.WriteLine("Received");
    Device.BeginInvokeOnMainThread(() =>
    {
        NotificationState.Instance.HaveNotification = true;
    });
};

核心注意点

无论用哪种方法,必须通过Device.BeginInvokeOnMainThread将属性更新操作切换到UI线程,否则可能导致UI不更新或抛出线程异常。

内容的提问来源于stack exchange,提问作者Gary H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:58:12