繁体   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