使用Xamarin BeginInvokeOnMainThread而不使用Xamarin.Forms

4

对于我确定会变成一个非常愚蠢的问题,我感到非常抱歉。

我正在使用 Android UI 而不是 Xamarin Forms 作为我的 Xamarin 应用程序的表现层,但我想要使用 Activity.RunOnUIThread(来自 Android), 所有 Xamarin 文档都建议使用 Device.BeginInvokeOnMainThread(来自 Xamarin.Forms)项目。显然,由于我没有在 xamarin.forms 项目中引用,因此我无法使用它。

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

3个回答

10

Windows有什么相应的版本吗?我有一些代码是在Android和Windows版本之间共享的。 - Stephen Price
@StephenPrice 您没有说明是哪种类型的Windows项目。在UWP上,您可以使用CoreDispatcher:https://learn.microsoft.com/en-us/uwp/api/Windows.UI.Core.CoreDispatcher#Windows_UI_Core_CoreDispatcher_RunAsync_Windows_UI_Core_CoreDispatcherPriority_Windows_UI_Core_DispatchedHandler_ - SushiHangover
这不是一个UWP应用程序。它可以在Windows 7上运行。查看项目引用会显示System.Windows.Forms。我从未见过类似的东西(考虑到它与Xamarin.Android应用程序共享了很多代码)。大部分应用程序使用OpenTK编写。应用程序的主页面继承自Form(所以,确实看起来像一个Windows.Forms应用程序)。 - Stephen Price
@StephenPrice 你正在寻找 Windows.Forms 中的 BeginInvoke:https://msdn.microsoft.com/zh-cn/library/system.windows.forms.control.begininvoke(v=vs.110).aspx - SushiHangover

6
如果您想从PCL / 共享代码和项目中的任何其他地方执行此操作,则有两种选择。 跨平台方式,使用本机机制
  • add this to PCL

    public class InvokeHelper
    {
        public static Action<Action> Invoker;
    
        public static void Invoke(Action action)
        {
            Invoker?.Invoke(action);
        }
    }
    
  • add this to iOS (e.g. AppDelegate)

    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
    {
        // ...
    
        InvokeHelper.Invoker = InvokeOnMainThread;
        return true;
    }
    
  • add this to Android (e.g. your application class)

    [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的答案。不过我已经给你的建议点了赞,因为我认为这是一个非常好的想法! - Syntax

1

这里有一个示例,来自官方文档

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

可以翻译为:

{{链接1:来源}}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接