Xamarin.Forms中可以有多个依赖项实例吗?

时间:2016-07-28 14:15:46

标签: xamarin.forms

我已经镜像了XLabs的一些代码,可以从我这里获取设备上的网络状态跟踪:Xlabs INetwork Android Implementation

我几乎将它与编码标准对齐并更改了一些方法名称 - 一切正常,除了某些原因在Android实现上我无法让我的事件处理程序响应,就像他们一样在iOS上做。

这是我对Android的改编:

[assembly: Dependency(typeof(STM.Droid.DependencyInjection.Network))]
[assembly: UsesPermission("android.permission.ACCESS_NETWORK_STATE")]
[assembly: UsesPermission("android.permission.ACCESS_WIFI_STATE")]
[assembly: UsesPermission("android.permission.CHANGE_NETWORK_STATE")]
[assembly: UsesPermission("android.permission.CHANGE_WIFI_STATE")]
namespace Namespace.Droid
{
    [BroadcastReceiver(Enabled = true)]
    [IntentFilter(new [] { Android.Net.ConnectivityManager.ConnectivityAction })]
    public class Network : BroadcastReceiver, INetwork
    {
        /// <summary>
        /// Internets the connection status.
        /// </summary>
        /// <returns>NetworkStatus.</returns>
        public NetworkStatus GetConnectionStatus()
        {
            var status = NetworkStatus.NotReachable;

            using (var cm = (ConnectivityManager)Application.Context.GetSystemService(Context.ConnectivityService))
            using (var ni = cm.ActiveNetworkInfo)
            {
                if (ni != null && ni.IsConnectedOrConnecting)
                {
                    var name = ni.TypeName.ToUpper();
                    if (name.Contains("WIFI"))
                    {
                        status = NetworkStatus.ReachableViaWiFiNetwork;
                    }
                    else if (name.Contains("MOBILE"))
                    {
                        status = NetworkStatus.ReachableViaCarrierDataNetwork;
                    }
                    else
                    {
                        status = NetworkStatus.ReachableViaUnknownNetwork;
                    }
                }
            }

            return status;
        }

        private readonly object lockObject = new object();
        private EventHandler<NetworkStatus> _reachabilityChanged;
        public event EventHandler<NetworkStatus> ReachabilityChanged
        {
            add
            {
                lock (this.lockObject)
                {
                    this._reachabilityChanged += value;
                }
            }

            remove
            {
                lock (this.lockObject)
                {
                    this._reachabilityChanged -= value;
                }
            }
        }

        /// <summary>
        /// Occurs when [reachability changed].
        /// </summary>
//      public event EventHandler<NetworkStatus> ReachabilityChanged;

        /// <summary>
        /// Determines whether the specified host is reachable.
        /// </summary>
        /// <param name="host">The host.</param>
        /// <param name="timeout">The timeout.</param>
        public Task<bool> IsReachableAsync(string host, TimeSpan timeout)
        {
            return Task.Run(
                () =>
                {
                    try
                    {
                        var address = InetAddress.GetByName(host);

                        return address != null; // && (address.IsReachable((int)timeout.TotalMilliseconds) || );
                    }
                    catch (UnknownHostException)
                    {
                        return false;
                    }
                });
        }

        /// <summary>
        /// Determines whether [is reachable by wifi] [the specified host].
        /// </summary>
        /// <param name="host">The host.</param>
        /// <param name="timeout">The timeout.</param>
        public async Task<bool> IsReachableByWifiAsync(string host, TimeSpan timeout)
        {
            return GetConnectionStatus() == NetworkStatus.ReachableViaWiFiNetwork && await IsReachableAsync(host, timeout);
        }

        /// <summary>
        /// This gets called by OS when the <see cref="ConnectivityManager.ConnectivityAction"/> <see cref="Intent"/> fires.
        /// </summary>
        /// <param name="context">Context for the intent.</param>
        /// <param name="intent">Intent information.</param>
        public override void OnReceive(Context context, Intent intent)
        {
            // this is a workaround - which oddly enough forwards events the way i would expect it to.
            MessagingCenter.Send(this as INetwork, string.Empty, GetConnectionStatus());

            // THIS IS ALWAYS NULL!
            var handler = _reachabilityChanged;
            if (handler != null)
            {
                var connectionStatus = this.GetConnectionStatus();
                handler(this, connectionStatus);
            }
        }
    }
}

有问题的错误发生在OnReceive。

在调试过程中,我注意到处理程序在PCL端正确连接 - 在_reachabilityChanged字段上只有奇怪的空白。

由于调试表明我显然正在

{md50e2cce2f1202796e628729fe0540389b.Network@b422684}

关于&#34;这个&#34;

的机器人OnReceive方法

在PCL方面我正在接受

{md50e2cce2f1202796e628729fe0540389b.Network@b562641}

调用DependencyService.Get

对我来说,这看起来像处理程序列表为空的原因,是因为我在另一个实例上订阅我的处理程序,因此当另一个网络实例调用OnReceive时,不会获得任何处理程序。

Xamarin.Forms DependencyService甚至可以提供2个或更多实例实例吗?因为那会让我感到惊讶......

更新:

如果有人需要解决方法 - 这也有效:

public event EventHandler<NetworkStatus> ReachabilityChanged
        {
            add { MessagingCenter.Subscribe(value.Target, string.Empty, (INetwork d, NetworkStatus a) => value(d, a)); }
            remove { MessagingCenter.Unsubscribe<INetwork>(value.Target, string.Empty); }
        }

1 个答案:

答案 0 :(得分:0)

对于新实例 _client = DependencyService.Get<YOUINTERFACE>(DependencyFetchTarget.NewInstance); 默认情况下,DependencyService为单身