【问题标题】:Why does a Global object lead to non working code?为什么全局对象会导致无法工作的代码?
【发布时间】:2019-10-20 16:55:33
【问题描述】:

我有一个非常基本的 android 应用程序。其中大部分仍然来自模板。我为 XMPP 客户端使用自己的类库。现在发生的事情是,如果我声明一个全局 TextView 用于事件或不同的方法(OnCreate、OnResume 等),我的事件似乎不会被引发。 我的图书馆绝对不是原因,因为我在不同的情况下对其进行了测试。

[Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)]
    public class MainActivity : AppCompatActivity
    {
        public XMPPClient client;
        TextView consoleText;

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.activity_main);

            Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);

            FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab);
            fab.Click += FabOnClick;

            //consoleText = FindViewById<TextView>(Resource.Id.consoleText);

            client = new XMPPClient("10.0.2.2", 5222, "chris3", "Define")
            {
                AuthenticationInfo = true
            };

            client.OnPublishEvent += Client_OnPublishEvent;
            client.OnConnection += Client_OnConnection;
            client.OnMessageReceived += Client_OnMessageReceived;
        }

        private void Client_OnMessageReceived(object sender, MessageEventArgs e)
        {
            //consoleText.Text += "\nMessage: " + e.text + " from " + e.from;
            Log.Debug("mytag", "Message!");
        }

        private void Client_OnPublishEvent(object sender, SubscriptionEventArgs e)
        {
            //consoleText.Text += "\nPublication: " + e.title + " with content " + e.content + " at " + e.published;
            Log.Debug("mytag", "Publication");
        }

        private void Client_OnConnection(object sender, ConnectionEventArgs e)
        {
            //consoleText.Text += "\nConnection status changed: " + e.Status;
            Log.Debug("mytag", "ConnectionChange");
        }

        public override bool OnCreateOptionsMenu(IMenu menu)
        {
            MenuInflater.Inflate(Resource.Menu.menu_main, menu);
            return true;
        }

        public override bool OnOptionsItemSelected(IMenuItem item)
        {
            int id = item.ItemId;
            if (id == Resource.Id.action_subscribe)
            {
                client.Subscribe("Node1");
                Log.Debug("mytag", "Subscribed");
                return true;
            }

            return base.OnOptionsItemSelected(item);
        }

        private void FabOnClick(object sender, EventArgs eventArgs)
        {
            View view = (View) sender;
            client.Connect();
        }
    }

当 TextView 控制台文本对象存在时,我的 OnConnection 事件在开始时被触发,当我关闭客户端时。 但是,如果它不存在,则每个事件都可以正常工作。 现在我是 Xamarin 的初学者,我对问题的根源非常感兴趣。

【问题讨论】:

  • 我对 Xamarin 不太熟悉,但我猜想它与跨线程访问 UI 控件有关。您可能应该在 UI 线程上 Invoke
  • 您似乎没有在 OnCreate 方法中的任何位置分配“consoleText”?
  • @Tubif-Fux 您收到的错误信息是什么?什么是外部和内部堆栈跟踪?你能分享一下,以便我们更好地帮助你吗?还要尝试放置一个异常捕获点,这样您就可以准确地看到引发异常的位置
  • @Saamer 没有错误。这就是问题所在。 TextView 只是没有改变,似乎冻结了程序,直到我调用我的 client.Close() 方法。

标签: c# android xamarin xamarin.android android-7.0-nougat


【解决方案1】:

您可能需要封装要针对主调度程序(UI 线程)处理的文本分配。

例如,它看起来像这样。

private void Client_OnMessageReceived(object sender, MessageEventArgs e)
{
    Activity.RunOnUiThread(() => {
        consoleText.Text += "\nMessage: " + e.text + " from " + e.from;
    });

    Log.Debug("mytag", "Message!");
}

试一试,如果它仍然有错误,请告诉我,不要忘记你需要将所有 consoleText.Text 分配包含在其中。

Activity.RunOnUiThread(() => {
});

// You might not need the Activity part, I can't remember exactly which 
// one it is for an AppCompatActivity.

RunOnUiThread(() => {
});

【讨论】:

  • 完美运行。谢谢 :) 我会调查一下,所以下次我知道实际发生了什么。
  • @TubifFux 很可能 XMPPClient 使用任务来处理事件,并且这些在不同的线程上执行。他们可能在某处隐藏了一些关于它的文档,但我很高兴答案有所帮助。
猜你喜欢
  • 1970-01-01
  • 2020-03-08
  • 2011-06-25
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多