AndroidThreadingInterface.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using System;
  2. using System.Reactive.Disposables;
  3. using System.Threading;
  4. using Android.OS;
  5. using Avalonia.Platform;
  6. using Avalonia.Threading;
  7. using App = Android.App.Application;
  8. namespace Avalonia.Android
  9. {
  10. internal sealed class AndroidThreadingInterface : IPlatformThreadingInterface
  11. {
  12. private Handler _handler;
  13. private static Thread s_uiThread;
  14. public AndroidThreadingInterface()
  15. {
  16. _handler = new Handler(App.Context.MainLooper);
  17. }
  18. public void RunLoop(CancellationToken cancellationToken) => throw new NotSupportedException();
  19. public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
  20. {
  21. if (interval.TotalMilliseconds < 10)
  22. interval = TimeSpan.FromMilliseconds(10);
  23. object l = new object();
  24. var stopped = false;
  25. Timer timer = null;
  26. var scheduled = false;
  27. timer = new Timer(_ =>
  28. {
  29. lock (l)
  30. {
  31. if (stopped)
  32. {
  33. timer.Dispose();
  34. return;
  35. }
  36. if (scheduled)
  37. return;
  38. scheduled = true;
  39. EnsureInvokeOnMainThread(() =>
  40. {
  41. try
  42. {
  43. tick();
  44. }
  45. finally
  46. {
  47. lock (l)
  48. {
  49. scheduled = false;
  50. }
  51. }
  52. });
  53. }
  54. }, null, TimeSpan.Zero, interval);
  55. return Disposable.Create(() =>
  56. {
  57. lock (l)
  58. {
  59. stopped = true;
  60. timer.Dispose();
  61. }
  62. });
  63. }
  64. private void EnsureInvokeOnMainThread(Action action) => _handler.Post(action);
  65. public void Signal(DispatcherPriority prio)
  66. {
  67. EnsureInvokeOnMainThread(() => Signaled?.Invoke(null));
  68. }
  69. public bool CurrentThreadIsLoopThread
  70. {
  71. get
  72. {
  73. if (s_uiThread != null)
  74. return s_uiThread == Thread.CurrentThread;
  75. var isOnMainThread = OperatingSystem.IsAndroidVersionAtLeast(23)
  76. ? Looper.MainLooper.IsCurrentThread
  77. : Looper.MainLooper.Thread.Equals(Java.Lang.Thread.CurrentThread());
  78. if (isOnMainThread)
  79. {
  80. s_uiThread = Thread.CurrentThread;
  81. return true;
  82. }
  83. return false;
  84. }
  85. }
  86. public event Action<DispatcherPriority?> Signaled;
  87. }
  88. }