【问题标题】:View on New Activity Not Updating On UI Thread查看未在 UI 线程上更新的新活动
【发布时间】:2015-10-11 10:48:39
【问题描述】:

遗憾的是,这段代码大多过于复杂,无法发布所有空隙。但是,我会尽力提供可能导致问题的少量代码。

所以我有一些东西在表面下运行,每当数据库上的东西更新时就会推出广播(它基本上是一个在 android 上监视服务器(未连接到互联网的服务器)的接口。)。我有广播接收器,它们正在监听这些广播,并在我们得到我们正在寻找的广播时在处理程序上运行一个 Runnable。

我正在使用从主要活动中调用的片段活动。此活动具有可变数量的片段,这些片段具有可变数量的“小部件”。这些小部件有自己的广播接收器,如上所述,它们正在侦听和响应。因此,每个广播仅在创建视图时注册,在删除时取消注册,因此每个广播接收器都包含对该项目的引用。

问题是,当我打开第二个活动时,在我的主要活动上使用相同的确切工作逻辑不起作用。出于某种原因,当我请求它这样做时,视图不会更新(例如 textView.setText("blah") 将在 Main Activity 上显示 "blah",但在这个新 Activity 上不显示任何内容)。使用打印语句,我注意到它认为它已更新,所以如果我调用“textView.setText(“blah”)”然后打印“textView.getText()”它会打印出“blah”,尽管有注释显示这在 UI 上。

这是我用来从 BroadcastReceiver 中调用任务的代码(注意 item 是对 item 的弱引用):

task = new MyRunnable();
if (item.get().getView() == null) return;
item.get().getView().post(task);

这是更新可运行文件之一的代码(其中 param 是广播的意图,context 是应用程序上下文,nameOfTextView 是文本视图的名称。):

String arg = param.getStringExtra(broadcast);
if (arg == null) return;

int id = context.getResources().getIdentifier(nameOfTextView, 
    "id", context.getPackageName());
View view = item.get().getView();
if (id == 0 || view == null || !view.isShown()) return;

TextView v = (TextView) view.findViewById(id);
v.setText(arg);

我一直在这几个小时没有运气。我最好的猜测是,出于某种原因,它没有引用正确的小部件。但是,这似乎不太可能,因为每个广播都是由小部件创建的,这意味着它传递的引用应该是有效的。

提前感谢您的帮助!

更新

在@Mark Herscher 提出了很好的建议后,我确​​定我的猜测是不正确的。实际上,它试图更改的视图与 UI 上显示的视图相同。我检查了三次,发现了一个问题并修复了线程运行两次的问题,但 UI 仍然无法正确更新。

同样,在 Main Activity 上使用相同的广播和可运行文件似乎不会发生这种情况。此问题与其他活动无关。

对于那些询问的人,这里是启动其他活动的几行代码:

Intent i = new Intent(MainActivity.this, GlobalSettingsActivity.class);
i.putExtra(REQUEST_CODE, GLOBAL_SETTINGS);
startActivityForResult(i, GLOBAL_SETTINGS);

这些活动扩展了一个使用相同代码生成的超类型。

【问题讨论】:

  • 如何创建第二个活动?您确定第二个 Activity 中的 BroadcastReceiver 确实收到了广播吗?
  • 你好@JohnnyAW。是的,我确信他们正在接收广播。有关该项目的一些更改信息,并且该信息正在正确更改。第二个活动是通过标准startActivityForResult() 创建的。
  • 所以你看到了第二个活动和初始值,但是你不能改变这些值,对吧?你能尝试完成第一个活动吗?
  • @JohnnyAW 有点正确。只有 UI 没有更新。与这些显示相关的值正在更新。因此,当我旋转屏幕(或者更确切地说,销毁并重新创建视图)时,更改是可见的,因为它会保存数据然后从中提取数据(或者如果那里没有任何内容,则显示一些标准消息/显示)。跨度>
  • 完成第一个活动怎么样?如果您添加一个按钮并在单击时更改值怎么办?

标签: java android multithreading android-fragments


【解决方案1】:

我怀疑您是否在第二个活动中启动了 AsyncTask。请确保您当前的活动没有启动 AsyncTask。如果 AsyncTask 在后台执行,请评论它并再次测试应用程序。让我知道你的结果。

【讨论】:

  • 没有异步任务正在运行。我什至没有做过。
  • view.post(Runnable r) 的基本要求是视图应该附加到窗口上以便 Runnable 被执行。 View.post() :将 Runnable 添加到消息队列中。 runnable 将在用户界面线程上运行。仅当此视图附加到窗口时,才能从 UI 线程外部调用此方法。但是,我认为 handler.post() 和 activity.runOnUIThread() 都很好。也试试...
  • @RoseR 检查时请告诉我们。
  • 我们都很想知道你的结果和发现,这就是我打扰你的原因。对不起,如果觉得恶心。
  • 您好,我不太清楚您在说什么?正如我的代码清楚地显示的那样,我正在使用 view.post() 并发布一个可运行的?尽管我已将其更改为简单的 new Handler.post()。这还没有解决问题。
【解决方案2】:

我同意这听起来像是您持有对旧视图的引用并改为更新它。

要对此进行测试,请在 Activity 的 onCreate() 中将所有相关视图的 tag* 设置为随机数。它需要一个对象,但您可以获取一个 int,然后将其转换为 Integer。然后,您可以在调试时检索标记值并打印它们的值。这应该有助于告诉您是否确实在更新同一个实例,或者您是否有多个不需要的实例。

当然,这并不能帮助您解决是如何发生的,而且如果没有更多代码,这很难说。

【讨论】:

  • 好建议!我会立即尝试并告诉你进展如何。
  • 经过一些彻底的测试,我确定该视图实际上与正在显示的视图相同(标记它并在将标记添加到视图层次结构之前保存标记,当它打印这样做是为了确定它是否多次这样做,等等)。
  • 嗯,这几乎令人失望。 :) 我此时不知所措。我会继续考虑的。
  • 由于问题“不应该发生”,这就是我要做的:复制整个项目并开始从中删除内容,直到问题消失。简化逻辑,删除所有无关紧要的 GUI 代码,并将其降到最低限度,仍然可以在没有任何额外部分的情况下演示问题。然后希望您可以在此处发布此简化代码,或者您将进行更改,问题就会消失,然后您就会知道在哪里查找。
  • 可悲的是,这个项目是几千行代码,可能有几万行。这很简单,但不幸的是,在短暂的工作时间内这是不可能的。
【解决方案3】:

我注意到代码 if (arg == null) 返回,但 String 参数可能为空。对于调试建议,在 if 块之后执行 Log.d(TAG, "param= " + arg);。如果您想查看是否存在并发问题,您可以执行 arg = arg + (increment number) 之类的代码。然后编码 Log.d。

您的帖子对问题不太清楚,我建议您在帖子底部的某处再次说明问题。

【讨论】:

  • 是的,但是我在代码末尾到达了一个打印语句,它正确地打印了正确的文本。正如我在问题陈述中提到的,我已经向视图询问了文本并得到了正确的文本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多