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

在Xamarin.Forms中使用Rx.Net:OnNext事件未触发问题排查

问题:Rx.Net OnNext事件未触发的排查与解决方法

问题场景

希望将Rx.Net的Subject封装在独立的RxNetHandler类中,实现多类共享,但MainPage中的订阅始终无法接收OnNext事件。若将Subject直接放在InfoStorageService类中则可正常工作,需要解决实例共享的问题。

代码示例

RxNetHandler类

public class RxNetHandler
{
    public readonly ReplaySubject<List<InfoDto>> InfoSubject = new(1);
}

InfoStorageService类

public class InfoStorageService
{
    private readonly RxNetHandler _rxNetHandler = new();
    private HttpClient _httpClient;
    private List<InfoDto> _infos = new();

    public InfoStorageService()
    {
        InitHttps();
    }

    public async Task GetInfosDetails()
    {
        var response = await _httpClient.GetAsync("https://jsonplaceholder.typicode.com/posts?userId=1");
        var content = response.Content;

        if (response.IsSuccessStatusCode)
        {
            var jsonResponse = await content.ReadAsStringAsync();
            _infos = JsonConvert.DeserializeObject<List<InfoDto>>(jsonResponse);
        }
        else
        {
            throw new Exception(((int)response.StatusCode).ToString() + " - " + response.ReasonPhrase);
        }

        _rxNetHandler.InfoSubject.OnNext(_infos);
    }
 }

MainPage类

public partial class MainPage : ContentPage
{
    private readonly RxNetHandler _rxNetHandler = new();
    private readonly InfoStorageService _infoStorage = new();
    private List<InfoDto> _infos = new();
    private IDisposable _disposed;

    public MainPage()
    {
        InitializeComponent();
        InitData();
    }

    protected override void OnAppearing()
    {
        _disposed = _rxNetHandler.InfoSubject.Subscribe(
            infos =>
            {
                _infos = infos;
            },
            () =>
            {
                Console.WriteLine("[ completed ]");
            }
        );
    }

    private async void InitData()
    {
        await _infoStorage.GetInfosDetails();
        InfoListView.ItemSelected += InfoListOnItemSelected;
    }
}

问题原因

核心问题是RxNetHandler实例不共享:
InfoStorageService和MainPage各自通过new()创建了独立的RxNetHandler对象,两者的InfoSubject是完全分离的实例。InfoStorageService调用OnNext时,是在自己的Subject上发送消息,而MainPage订阅的是另一个完全无关的Subject,因此无法接收到消息。

解决方案

方案1:单例模式确保实例唯一

修改RxNetHandler为单例,让所有类共享同一个实例:

public class RxNetHandler
{
    private RxNetHandler() {}
    public static RxNetHandler Instance { get; } = new RxNetHandler();
    public readonly ReplaySubject<List<InfoDto>> InfoSubject = new(1);
}

修改InfoStorageService和MainPage的引用方式:

  • InfoStorageService中:private readonly RxNetHandler _rxNetHandler = RxNetHandler.Instance;
  • MainPage中:private readonly RxNetHandler _rxNetHandler = RxNetHandler.Instance;

方案2:依赖注入传递实例

如果项目使用依赖注入(如.NET MAUI的内置DI),将RxNetHandler注册为单例:
在Program.cs中添加:

builder.Services.AddSingleton<RxNetHandler>();

修改类的构造函数实现注入:

// InfoStorageService构造函数
public InfoStorageService(RxNetHandler rxNetHandler)
{
    _rxNetHandler = rxNetHandler;
    InitHttps();
}

// MainPage构造函数
public MainPage(RxNetHandler rxNetHandler, InfoStorageService infoStorage)
{
    _rxNetHandler = rxNetHandler;
    _infoStorage = infoStorage;
    InitializeComponent();
    InitData();
}

方案3:手动传递同一实例

在MainPage中创建RxNetHandler实例,传递给InfoStorageService:

// MainPage构造函数
public MainPage()
{
    _rxNetHandler = new RxNetHandler();
    _infoStorage = new InfoStorageService(_rxNetHandler);
    InitializeComponent();
    InitData();
}

// InfoStorageService构造函数
public InfoStorageService(RxNetHandler rxNetHandler)
{
    _rxNetHandler = rxNetHandler;
    InitHttps();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 07:07:45