[Android] Always set a non-null Device.Info (#504)
authorAlan McGovern <alanmcgovern@users.noreply.github.com>
Tue, 8 Nov 2016 08:14:44 +0000 (08:14 +0000)
committerStephane Delcroix <stephane@delcroix.org>
Tue, 8 Nov 2016 08:14:44 +0000 (09:14 +0100)
When we run under the context of layoutlib the `Context` object
that is created will not implement IDeviceInfoProvider. All this
means is that we will not get change notifications when the
orientation changes, but that's ok! This won't happen anyway.

If we instantiate the Device.Info object then everywhere else in
the code will be able to get access to the screen properties.

Fixes https://bugzilla.xamarin.com/show_bug.cgi?id=44893

Xamarin.Forms.Platform.Android/Forms.cs

index fd74287..3d2a735 100644 (file)
@@ -130,10 +130,7 @@ namespace Xamarin.Forms
                                Device.info = null;
                        }
 
-                       // probably could be done in a better way
-                       var deviceInfoProvider = activity as IDeviceInfoProvider;
-                       if (deviceInfoProvider != null)
-                               Device.Info = new AndroidDeviceInfo(deviceInfoProvider);
+                       Device.Info = new AndroidDeviceInfo(activity);
 
                        var ticker = Ticker.Default as AndroidTicker;
                        if (ticker != null)
@@ -190,17 +187,21 @@ namespace Xamarin.Forms
 
                class AndroidDeviceInfo : DeviceInfo
                {
-                       readonly IDeviceInfoProvider _formsActivity;
+                       bool disposed;
+                       readonly Context _formsActivity;
                        readonly Size _pixelScreenSize;
                        readonly double _scalingFactor;
 
                        Orientation _previousOrientation = Orientation.Undefined;
 
-                       public AndroidDeviceInfo(IDeviceInfoProvider formsActivity)
+                       public AndroidDeviceInfo(Context formsActivity)
                        {
                                _formsActivity = formsActivity;
                                CheckOrientationChanged(_formsActivity.Resources.Configuration.Orientation);
-                               formsActivity.ConfigurationChanged += ConfigurationChanged;
+                               // This will not be an implementation of IDeviceInfoProvider when running inside the context
+                               // of layoutlib, which is what the Android Designer does.
+                               if (_formsActivity is IDeviceInfoProvider)
+                                       ((IDeviceInfoProvider) _formsActivity).ConfigurationChanged += ConfigurationChanged;
 
                                using (DisplayMetrics display = formsActivity.Resources.DisplayMetrics)
                                {
@@ -224,7 +225,11 @@ namespace Xamarin.Forms
 
                        protected override void Dispose(bool disposing)
                        {
-                               _formsActivity.ConfigurationChanged -= ConfigurationChanged;
+                               if (disposing && !disposed) {
+                                       disposed = true;
+                                       if (_formsActivity is IDeviceInfoProvider)
+                                               ((IDeviceInfoProvider) _formsActivity).ConfigurationChanged -= ConfigurationChanged;
+                               }
                                base.Dispose(disposing);
                        }