簡體   English   中英

MVVMCross Messenger-訂閱靜態類中的消息

[英]MVVMCross Messenger - Subscribing to messages in static class

我只是在考慮實施MVVMCross Messenger解決方案,當從iOS應用程序或PCL發布時,該解決方案使我能夠將信息上傳到Google Analytics(分析)。

我的問題是發布后未觸發訂閱代理。 您可以從靜態類訂閱MVVMCross Messenger訂閱嗎?

靜態類中的訂閱

public static class GoogleAnalyticsWrapper //: IDisposable
{
    private const string TrackingId = "xxxxxxxxxxx";

    private static readonly IMvxMessenger messenger;
    private static readonly MvxSubscriptionToken screenNameToken;
    private static  readonly MvxSubscriptionToken eventToken;
    private static  readonly MvxSubscriptionToken exceptionToken;
    private static  readonly MvxSubscriptionToken performanceToken;
    private static  readonly MvxSubscriptionToken publishToken;
    private static  bool disposed = false;
    private static  SafeHandle handle;

    static GoogleAnalyticsWrapper()
    {
        Gai.SharedInstance.DispatchInterval = 60;
        Gai.SharedInstance.TrackUncaughtExceptions = true;

        Gai.SharedInstance.GetTracker(TrackingId); 

        messenger = new MvxMessengerHub();// Mvx.Resolve<IMvxMessenger>();
        screenNameToken = messenger.Subscribe<GaScreenNameMessage>((m) => SetScreenName(m));

        int count = messenger.CountSubscriptionsFor<GaScreenNameMessage>();

        eventToken = messenger.Subscribe<GaEventMessage>(CreateEvent);
        exceptionToken = messenger.Subscribe<GaExceptionMessage>(CreateException);
        performanceToken = messenger.Subscribe<GaPerformanceTimingMessage>(CreatePerformanceMetric);
        publishToken = messenger.Subscribe<GaPublishMessage>(PublishAll);
    }

    public static string Dummy { get; set; }

    public static void SetScreenName(GaScreenNameMessage message) 
    {
        System.Diagnostics.Debugger.Break();
        Gai.SharedInstance.DefaultTracker.Set(GaiConstants.ScreenName, message.ScreenName);
        Gai.SharedInstance.DefaultTracker.Send(DictionaryBuilder.CreateScreenView().Build());
    }

    public static  void CreateEvent(GaEventMessage message) 
        => Gai.SharedInstance.DefaultTracker.Send(DictionaryBuilder.CreateEvent(message.Category, message.Action, message.Label, message.Number).Build());

    private static  void CreateException(GaExceptionMessage message) 
        => Gai.SharedInstance.DefaultTracker.Send(DictionaryBuilder.CreateException(message.ExceptionMessage, message.IsFatal).Build());

    private static  void CreatePerformanceMetric(GaPerformanceTimingMessage message)
        => Gai.SharedInstance.DefaultTracker.Send(DictionaryBuilder.CreateTiming(message.Category, message.Milliseconds, message.Name, message.Label).Build());

    private static  void PublishAll(GaPublishMessage message) 
        => Gai.SharedInstance.Dispatch();

    public static  void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Dispose managed resources.
                if (handle != null)
                {
                    handle.Dispose();
                }
            }

            // Dispose unmanaged managed resources.
            disposed = true;
        }
    }
}

出版物

messengerService.Publish<GaEventMessage>(new GaEventMessage(this, "Event", "Publish Event", "Publish Event From First View Model", 123));

問題是,您正在靜態類中創建一個新的MvxMessengerHub ,但是( 我猜是 )將IMvxMessenger注入到您的使用類中,該類是由MvvMCross在初始化生命周期內創建的,因此是另一個實例。

簡單的解決方案是在App.cs中將其初始化,例如

public class App : Cirrious.MvvmCross.ViewModels.MvxApplication
{
    public override void Initialize()
    {
        // ...

        var m = Cirrious.CrossCore.Mvx.Resolve<IMvxMessenger>();
        GoogleAnalyticsWrapper.Initialize(m); 
        // ...
    }
}

用這樣的包裝紙

public static class GoogleAnalyticsWrapper
{
    static void Initialize(IMvxMessenger messenger)
    {
        Gai.SharedInstance.DispatchInterval = 60;
        Gai.SharedInstance.TrackUncaughtExceptions = true;
        Gai.SharedInstance.GetTracker(TrackingId); 

        screenNameToken = messenger.Subscribe<GaScreenNameMessage>((m) => SetScreenName(m));

        int count = messenger.CountSubscriptionsFor<GaScreenNameMessage>();

        eventToken = messenger.Subscribe<GaEventMessage>(CreateEvent);
        exceptionToken = messenger.Subscribe<GaExceptionMessage>(CreateException);
        performanceToken = messenger.Subscribe<GaPerformanceTimingMessage>(CreatePerformanceMetric);
        publishToken = messenger.Subscribe<GaPublishMessage>(PublishAll);
    }

    // ...
}   

高級提示

但是據我所知,在這種情況下,您甚至不需要消息傳遞,因為它是一對一的“通信”。 如果您將GoogleAnalyticsWrapper的功能移入定義明確的服務中,例如:

interface ITrackingService
{  
    void SetScreenName(GaScreenNameMessage message);
    void CreateEvent(GaEventMessage message);
    void CreateException(GaExceptionMessage message);
    void CreatePerformanceMetric(GaPerformanceTimingMessage message);
    void PublishAll(GaPublishMessage message);
}

public class GoogleAnalyticsTrackingService : ITrackingService
{
    private const string TrackingId = "xxxxxxxxxxx";

    public GoogleAnalyticsTrackingService()
    {
        Gai.SharedInstance.DispatchInterval = 60;
        Gai.SharedInstance.TrackUncaughtExceptions = true;

        Gai.SharedInstance.GetTracker(TrackingId);
    }

    public void SetScreenName(GaScreenNameMessage message) 
    {
        Gai.SharedInstance.DefaultTracker.Set(GaiConstants.ScreenName, message.ScreenName);
        Gai.SharedInstance.DefaultTracker.Send(DictionaryBuilder.CreateScreenView().Build());
    }

    public void CreateEvent(GaEventMessage message) 
    {
        Gai.SharedInstance.DefaultTracker.Send(DictionaryBuilder.CreateEvent(message.Category, message.Action, message.Label, message.Number).Build());
    }   

    private void CreateException(GaExceptionMessage message) 
    {
        Gai.SharedInstance.DefaultTracker.Send(DictionaryBuilder.CreateException(message.ExceptionMessage, message.IsFatal).Build());
    }

    private void CreatePerformanceMetric(GaPerformanceTimingMessage message)
    {
        Gai.SharedInstance.DefaultTracker.Send(DictionaryBuilder.CreateTiming(message.Category, message.Milliseconds, message.Name, message.Label).Build());
    }

    private void PublishAll(GaPublishMessage message) 
    {
        Gai.SharedInstance.Dispatch();
    }
}

必須在您的應用中注冊

Mvx.LazyConstructAndRegisterSingleton<ITrackingService, GoogleAnalyticsTrackingService>();

可以與構造函數注入或手動解析一起使用

class MyViewModel : MvxViewModel 
{
    public MyViewModel(ITrackingService tracking)
    {
         tracking.CreateEvent(new GaEventMessage(this, "Event", "Publish Event", "Publish Event From First View Model", 123));
    }
}

// or
class MyViewModel : MvxViewModel 
{
    public MyViewModel()
    {
         var tracking = Mvx.Resolve<ITrackingService>();
         tracking.CreateEvent(new GaEventMessage(this, "Event", "Publish Event", "Publish Event From First View Model", 123));
    }
}

仍然存在一個問題:界面仍然依賴於Google Analytics(分析)。 但是可以通過使用多個參數而不是參數對象來輕松刪除依賴項。

interface ITrackingService
{
    void CreateEvent(string eventName, string title, string message, params object[] additionalParams);
    // ...
} 

// call:
tracking.CreateEvent("Event", "Publish Event", "Publish Event From First View Model", 123);

這樣,如果您的涉眾決定切換到Adobe omniture或其他工具,您就可以對它進行單元測試並輕松地交換跟蹤服務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM