diff options
9 files changed, 136 insertions, 224 deletions
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28953.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28953.cs new file mode 100644 index 00000000..3a357863 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28953.cs @@ -0,0 +1,116 @@ +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; +using System; +using System.Threading.Tasks; + +#if UITEST +using Xamarin.UITest; +using NUnit.Framework; +#endif + +namespace Xamarin.Forms.Controls.Issues +{ + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Bugzilla, 28953, "Device.StartTimer (still) behaves differently on different platforms", PlatformAffected.All)] + public class Bugzilla28953 : TestContentPage // or TestMasterDetailPage, etc ... + { + int count = 0, count2 = 0; + Label label2, label3; + bool shouldStop, shouldStop2; + + protected override void Init() + { + var stackLayout = new StackLayout + { + Orientation = StackOrientation.Vertical, + VerticalOptions = LayoutOptions.Center, + Spacing = 20 + }; + + var label1 = new Label + { + Text = "Click Start to start counting with a timer. Click Stop to reset. Both timers update text in UI thread." + }; + stackLayout.Children.Add(label1); + + label2 = new Label + { + Text = count.ToString(), + HorizontalTextAlignment = TextAlignment.Center, + }; + stackLayout.Children.Add(label2); + + label3 = new Label + { + Text = count2.ToString(), + HorizontalTextAlignment = TextAlignment.Center, + }; + stackLayout.Children.Add(label3); + + var button = new Button + { + Text = "Start" + }; + button.Clicked += Button_Clicked; + stackLayout.Children.Add(button); + + var button2 = new Button + { + Text = "Start (in background thread)" + }; + button2.Clicked += Button_Clicked2; + stackLayout.Children.Add(button2); + + Content = stackLayout; + } + + private void Button_Clicked(object sender, EventArgs e) + { + var button = sender as Button; + if (button.Text == "Start") + { + (sender as Button).Text = "Stop"; + shouldStop = false; + + Device.StartTimer(TimeSpan.FromMilliseconds(100), () => + { + label2.Text = count.ToString(); + count++; + return !shouldStop; + }); + } + else + { + button.Text = "Start"; + shouldStop = true; + count = 0; + } + } + + private void Button_Clicked2(object sender, EventArgs e) + { + var button = sender as Button; + if (button.Text == "Start (in background thread)") + { + (sender as Button).Text = "Stop (in background thread)"; + shouldStop2 = false; + + Task.Run(() => + { + Device.StartTimer(TimeSpan.FromMilliseconds(100), () => + { + label3.Text = count2.ToString(); + count2++; + return !shouldStop2; + }); + }); + } + else + { + button.Text = "Start (in background thread)"; + shouldStop2 = true; + count2 = 0; + } + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index 36ed04cb..16a2199d 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -36,6 +36,7 @@ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28570.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28796.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28939.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28953.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla29107.xaml.cs"> <DependentUpon>Bugzilla29107.xaml</DependentUpon> </Compile> diff --git a/Xamarin.Forms.Core.UnitTests/MockPlatformServices.cs b/Xamarin.Forms.Core.UnitTests/MockPlatformServices.cs index 5109cbb4..e8519b9e 100644 --- a/Xamarin.Forms.Core.UnitTests/MockPlatformServices.cs +++ b/Xamarin.Forms.Core.UnitTests/MockPlatformServices.cs @@ -119,57 +119,6 @@ namespace Xamarin.Forms.Core.UnitTests return AppDomain.CurrentDomain.GetAssemblies (); } - public ITimer CreateTimer (Action<object> callback) - { - return new MockTimer (new Timer (o => callback(o))); - } - - public ITimer CreateTimer (Action<object> callback, object state, int dueTime, int period) - { - return new MockTimer (new Timer (o => callback(o), state, dueTime, period)); - } - - public ITimer CreateTimer (Action<object> callback, object state, long dueTime, long period) - { - return new MockTimer (new Timer (o => callback(o), state, dueTime, period)); - } - - public ITimer CreateTimer (Action<object> callback, object state, TimeSpan dueTime, TimeSpan period) - { - return new MockTimer (new Timer (o => callback(o), state, dueTime, period)); - } - - public ITimer CreateTimer (Action<object> callback, object state, uint dueTime, uint period) - { - return new MockTimer (new Timer (o => callback(o), state, dueTime, period)); - } - - public class MockTimer : ITimer - { - readonly Timer timer; - public MockTimer (Timer timer) - { - this.timer = timer; - } - - public void Change (int dueTime, int period) - { - timer.Change (dueTime, period); - } - public void Change (long dueTime, long period) - { - timer.Change (dueTime, period); - } - public void Change (TimeSpan dueTime, TimeSpan period) - { - timer.Change (dueTime, period); - } - public void Change (uint dueTime, uint period) - { - timer.Change (dueTime, period); - } - } - public IIsolatedStorageFile GetUserStoreForApplication () { #if WINDOWS_PHONE diff --git a/Xamarin.Forms.Core/ITimer.cs b/Xamarin.Forms.Core/ITimer.cs deleted file mode 100644 index ba867dba..00000000 --- a/Xamarin.Forms.Core/ITimer.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace Xamarin.Forms -{ - //this will go once Timer is included in Pcl profiles - internal interface ITimer - { - void Change(int dueTime, int period); - void Change(long dueTime, long period); - void Change(TimeSpan dueTime, TimeSpan period); - void Change(uint dueTime, uint period); - } -}
\ No newline at end of file diff --git a/Xamarin.Forms.Core/Xamarin.Forms.Core.csproj b/Xamarin.Forms.Core/Xamarin.Forms.Core.csproj index 9bfb7ba2..2e10a1b2 100644 --- a/Xamarin.Forms.Core/Xamarin.Forms.Core.csproj +++ b/Xamarin.Forms.Core/Xamarin.Forms.Core.csproj @@ -369,7 +369,6 @@ <Compile Include="Tweener.cs" /> <Compile Include="IPlatformServices.cs" /> <Compile Include="UriTypeConverter.cs" /> - <Compile Include="ITimer.cs" /> <Compile Include="IIsolatedStorageFile.cs" /> <Compile Include="Grid.cs" /> <Compile Include="GridCalc.cs" /> diff --git a/Xamarin.Forms.Platform.Android/Forms.cs b/Xamarin.Forms.Platform.Android/Forms.cs index 3d2a735c..1ecf76d3 100644 --- a/Xamarin.Forms.Platform.Android/Forms.cs +++ b/Xamarin.Forms.Platform.Android/Forms.cs @@ -410,22 +410,15 @@ namespace Xamarin.Forms public void StartTimer(TimeSpan interval, Func<bool> callback) { - Timer timer = null; - bool invoking = false; - TimerCallback onTimeout = o => + var handler = new Handler(Looper.MainLooper); + handler.PostDelayed(() => { - if (!invoking) - { - invoking = true; - BeginInvokeOnMainThread(() => - { - if (!callback()) - timer.Dispose(); - invoking = false; - }); - } - }; - timer = new Timer(onTimeout, null, interval, interval); + if (callback()) + StartTimer(interval, callback); + + handler.Dispose(); + handler = null; + }, (long)interval.TotalMilliseconds); } double ConvertTextAppearanceToSize(int themeDefault, int deviceDefault, double defaultValue) @@ -472,36 +465,6 @@ namespace Xamarin.Forms return false; } - public class _Timer : ITimer - { - readonly Timer _timer; - - public _Timer(Timer timer) - { - _timer = timer; - } - - public void Change(int dueTime, int period) - { - _timer.Change(dueTime, period); - } - - public void Change(long dueTime, long period) - { - _timer.Change(dueTime, period); - } - - public void Change(TimeSpan dueTime, TimeSpan period) - { - _timer.Change(dueTime, period); - } - - public void Change(uint dueTime, uint period) - { - _timer.Change(dueTime, period); - } - } - public class _IsolatedStorageFile : IIsolatedStorageFile { readonly IsolatedStorageFile _isolatedStorageFile; diff --git a/Xamarin.Forms.Platform.WP8/WP8PlatformServices.cs b/Xamarin.Forms.Platform.WP8/WP8PlatformServices.cs index 30623088..cd9f44f9 100644 --- a/Xamarin.Forms.Platform.WP8/WP8PlatformServices.cs +++ b/Xamarin.Forms.Platform.WP8/WP8PlatformServices.cs @@ -137,36 +137,6 @@ namespace Xamarin.Forms return 'a' + v - 10; } - public class _Timer : ITimer - { - readonly Timer _timer; - - public _Timer(Timer timer) - { - _timer = timer; - } - - public void Change(int dueTime, int period) - { - _timer.Change(dueTime, period); - } - - public void Change(long dueTime, long period) - { - _timer.Change(dueTime, period); - } - - public void Change(TimeSpan dueTime, TimeSpan period) - { - _timer.Change(dueTime, period); - } - - public void Change(uint dueTime, uint period) - { - _timer.Change(dueTime, period); - } - } - public class _IsolatedStorageFile : IIsolatedStorageFile { readonly IsolatedStorageFile _isolatedStorageFile; diff --git a/Xamarin.Forms.Platform.WinRT/WindowsBasePlatformServices.cs b/Xamarin.Forms.Platform.WinRT/WindowsBasePlatformServices.cs index 49589a8a..310b66c3 100644 --- a/Xamarin.Forms.Platform.WinRT/WindowsBasePlatformServices.cs +++ b/Xamarin.Forms.Platform.WinRT/WindowsBasePlatformServices.cs @@ -29,12 +29,12 @@ namespace Xamarin.Forms.Platform.WinRT { internal abstract class WindowsBasePlatformServices : IPlatformServices { - CoreDispatcher _dispatcher; + readonly CoreDispatcher _dispatcher; - public WindowsBasePlatformServices(CoreDispatcher dispatcher) + protected WindowsBasePlatformServices(CoreDispatcher dispatcher) { if (dispatcher == null) - throw new ArgumentNullException("dispatcher"); + throw new ArgumentNullException(nameof(dispatcher)); _dispatcher = dispatcher; } @@ -57,9 +57,8 @@ namespace Xamarin.Forms.Platform.WinRT IReadOnlyList<StorageFile> files = query.GetFilesAsync().AsTask().Result; var assemblies = new List<Assembly>(files.Count); - for (var i = 0; i < files.Count; i++) + foreach (StorageFile file in files) { - StorageFile file = files[i]; try { Assembly assembly = Assembly.Load(new AssemblyName { Name = Path.GetFileNameWithoutExtension(file.Name) }); @@ -133,35 +132,5 @@ namespace Xamarin.Forms.Platform.WinRT timer.Stop(); }; } - - internal class WindowsTimer : ITimer - { - readonly Timer _timer; - - public WindowsTimer(Timer timer) - { - _timer = timer; - } - - public void Change(int dueTime, int period) - { - _timer.Change(dueTime, period); - } - - public void Change(long dueTime, long period) - { - Change(TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period)); - } - - public void Change(TimeSpan dueTime, TimeSpan period) - { - _timer.Change(dueTime, period); - } - - public void Change(uint dueTime, uint period) - { - Change(TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period)); - } - } } }
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.iOS/Forms.cs b/Xamarin.Forms.Platform.iOS/Forms.cs index 06cb1312..5361e13f 100644 --- a/Xamarin.Forms.Platform.iOS/Forms.cs +++ b/Xamarin.Forms.Platform.iOS/Forms.cs @@ -68,9 +68,7 @@ namespace Xamarin.Forms internal static void SendViewInitialized(this VisualElement self, UIView nativeView) { - var viewInitialized = ViewInitialized; - if (viewInitialized != null) - viewInitialized(self, new ViewInitializedEventArgs { View = self, NativeView = nativeView }); + ViewInitialized?.Invoke(self, new ViewInitializedEventArgs { View = self, NativeView = nativeView }); } class iOSExpressionSearch : ExpressionVisitor, IExpressionSearch @@ -117,15 +115,9 @@ namespace Xamarin.Forms public override Size PixelScreenSize { get; } - public override Size ScaledScreenSize - { - get { return _scaledScreenSize; } - } + public override Size ScaledScreenSize => _scaledScreenSize; - public override double ScalingFactor - { - get { return _scalingFactor; } - } + public override double ScalingFactor => _scalingFactor; protected override void Dispose(bool disposing) { @@ -136,7 +128,7 @@ namespace Xamarin.Forms class IOSPlatformServices : IPlatformServices { - static readonly MD5CryptoServiceProvider Checksum = new MD5CryptoServiceProvider(); + static readonly MD5CryptoServiceProvider s_checksum = new MD5CryptoServiceProvider(); public void BeginInvokeOnMainThread(Action action) { @@ -155,7 +147,7 @@ namespace Xamarin.Forms public string GetMD5Hash(string input) { - var bytes = Checksum.ComputeHash(Encoding.UTF8.GetBytes(input)); + var bytes = s_checksum.ComputeHash(Encoding.UTF8.GetBytes(input)); var ret = new char[32]; for (var i = 0; i < 16; i++) { @@ -198,10 +190,7 @@ namespace Xamarin.Forms return new _IsolatedStorageFile(IsolatedStorageFile.GetUserStoreForApplication()); } - public bool IsInvokeRequired - { - get { return !NSThread.IsMain; } - } + public bool IsInvokeRequired => !NSThread.IsMain; public void OpenUriAction(Uri uri) { @@ -210,8 +199,7 @@ namespace Xamarin.Forms public void StartTimer(TimeSpan interval, Func<bool> callback) { - NSTimer timer = null; - timer = NSTimer.CreateRepeatingScheduledTimer(interval, t => + NSTimer timer = NSTimer.CreateRepeatingTimer(interval, t => { if (!callback()) t.Invalidate(); @@ -238,36 +226,6 @@ namespace Xamarin.Forms return 'a' + v - 10; } - public class _Timer : ITimer - { - readonly Timer _timer; - - public _Timer(Timer timer) - { - _timer = timer; - } - - public void Change(int dueTime, int period) - { - _timer.Change(dueTime, period); - } - - public void Change(long dueTime, long period) - { - _timer.Change(dueTime, period); - } - - public void Change(TimeSpan dueTime, TimeSpan period) - { - _timer.Change(dueTime, period); - } - - public void Change(uint dueTime, uint period) - { - _timer.Change(dueTime, period); - } - } - public class _IsolatedStorageFile : IIsolatedStorageFile { readonly IsolatedStorageFile _isolatedStorageFile; |