【问题标题】:Xamarin BeginInvokeOnMainThread without Xamarin.Forms没有 Xamarin.Forms 的 Xamarin BeginInvokeOnMainThread
【发布时间】:2016-04-14 09:42:08
【问题描述】:

很抱歉,我确定这是一个非常愚蠢的问题..

我在 Xamarin 应用程序的表示层中使用的是 Android UI 而不是 Xamarin Forms,但我想使用 Activity.RunOnUIThread(来自 Android),所有 Xamarin 文档都建议使用 Device.BeginInvokeOnMainThread(来自 Xamarin.Forms)项目。显然我没有这个可用,因为我没有关于 xamarin.forms 项目的参考。

如果我不想使用 Forms,在哪里可以找到 Xamarin 中的 run-on-ui-thread 机制?

【问题讨论】:

    标签: xamarin xamarin.forms xamarin.android


    【解决方案1】:

    安卓:

    Android Activitys 有一个可以使用的RunOnUiThread 方法:

    RunOnUiThread  ( () => {
        // manipulate UI controls
    });
    

    参考:https://developer.xamarin.com/api/member/Android.App.Activity.RunOnUiThread/p/Java.Lang.IRunnable/

    iOS:

    InvokeOnMainThread (delegate {  
        // manipulate UI controls
    });
    

    【讨论】:

    • windows 等价物是什么?我有在 Android 版本和 Windows 版本之间共享的代码。
    • @StephenPrice 你没有说什么类型的Windows项目,在UWP上你可以使用CoreDispatcher:docs.microsoft.com/en-us/uwp/api/…
    • 它不是 UWP 应用。它在 Windows 7 上运行。查看项目引用显示 System.Windows.Forms。没有见过类似的东西(鉴于它与 Xamarin.Android 应用程序共享大量代码)。大多数应用程序都是使用 OpenTK 编写的。应用程序的主页继承自 Form(是的,看起来绝对像 Windows.Forms 应用程序。)
    • @StephenPrice 您正在寻找 Windows.Forms 的 BeginInvokemsdn.microsoft.com/en-us/library/…
    【解决方案2】:

    如果您想从您的 PCL/共享代码以及项目中的其他任何地方执行此操作。你有两个选择这样做。

    跨平台方式,使用原生机制

    • 将此添加到 PCL

      public class InvokeHelper
      {
          public static Action<Action> Invoker;
      
          public static void Invoke(Action action)
          {
              Invoker?.Invoke(action);
          }
      }
      
    • 将此添加到 iOS(例如 AppDelegate)

      public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
      {
          // ...
      
          InvokeHelper.Invoker = InvokeOnMainThread;
          return true;
      }
      
    • 将此添加到 Android(例如您的应用程序类)

      [Application]
      class MainApplication : Application
      {
          protected MainApplication(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
          {
          }
      
          public override void OnCreate()
          {
              base.OnCreate();
              InvokeHelper.Invoker = (action) =>
              {
                  var uiHandler = new Handler(Looper.MainLooper);
                  uiHandler.Post(action);
              };
          }
      }
      

    然后你可以从你的共享代码中调用

    InvokeHelper.Invoke(() => DoSomething("bla"));
    

    完整的跨平台方式

    你也可以跨平台实现InvokeHelper

    public class InvokeHelper
    {
        // assuming the static initializer is executed on the UI Thread.
        public static SynchronizationContext mainSyncronisationContext = SynchronizationContext.Current;
    
        public static void Invoke(Action action)
        {
            mainSyncronisationContext?.Post(_ => action(), null);
        }
    }
    

    【讨论】:

    • 这是一个非常好的解决方案,但是由于我主要在做一个更简单的解决方案并且现在只需要在纯 android 中使用它,所以我在下面给出了 Sushi 的答案。不过,我赞成您的建议,因为我认为这是一个非常好的主意!
    【解决方案3】:

    这里有一个从official documentation获得的例子:

    public class ThreadDemo : Activity
    {
      TextView textview;
    
      protected override void OnCreate (Bundle bundle)
      {
          base.OnCreate (bundle);
          // Create a new TextView and set it as our view
          textview = new TextView (this);
          textview.Text = "Working..";
          SetContentView (textview);
          ThreadPool.QueueUserWorkItem (o => SlowMethod ());
      }
    
      private void SlowMethod ()
      {
          Thread.Sleep (5000);
          RunOnUiThread (() => textview.Text = "Method Complete");
      }
    }
    

    基本上,如果你想运行多行代码,你可以这样做:

    RunOnUiThread(()=>{
      MethodOne();
      MethodTwo();
    });
    

    source

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-19
      • 2014-11-26
      • 1970-01-01
      • 2018-01-02
      相关资源
      最近更新 更多