Android – 如何在runOnUiThread中将数据传递给Runnable?

我需要更新一些UI,并使用runOnUiThread在UI线程内部进行
现在UI的数据来自另一个Thread,由data表示。

如何将数据传递给Runnable,以便它们可用于更新UI? Android似乎不允许直接使用数据。 有一种优雅的方式来做到这一点?

 public void OnNewSensorData(Data data) { runOnUiThread(new Runnable() { public void run() { //use data } }); } 

我的解决方案是在runnable中创建一个fioeld private Data sensordata ,并为其分配数据。 如果原始Data data是最终Data data ,则此方法有效。

 public void OnNewSensorData(final Data data) { runOnUiThread(new Runnable() { private Data sensordata = data; public void run() { //use sensordata which is equal to data } }); } 

Solutions Collecting From Web of "Android – 如何在runOnUiThread中将数据传递给Runnable?"

你发现的问题是

Java中的内部类捕获(“关闭”)定义它们的词法范围。 但它们只捕获声明为“最终”的variables。

如果这很清楚,那么这里有一个很好的讨论细节: 不能引用在不同方法中定义的内部类中的非finalvariables

但你的解决方案看起来不错 此外,如果data是最终的,您可以将代码简化为:

 public void OnNewSensorData(final Data data) { runOnUiThread(new Runnable() { public void run() { // use data here data.doSomething(); } }); } 

如果要避免使用中间最终variables(如Dan S所述),可以使用其他方法实现Runnable来设置数据:

 public class MyRunnable implements Runnable { private Data data; public void setData(Data _data) { this.data = _data; } public void run() { // do whatever you want with data } } 

然后,您可以像这样调用方法:

 public void OnNewSensorData(Data data) { MyRunnable runnable = new MyRunnable(); runnable.setData(data); runOnUiThread(runnable); } 

你也可以使MyRunnable的构造函数接受Data实例作为参数:

 public class MyRunnable implements Runnable { private Data data; public MyRunnable(Data _data) { this.data = _data; } public void run() { ... } } 

然后只说runOnUiThread(new MyRunnable(data));

我有一个类似的问题,我想把信息传递给线程。 要用android系统解决它,我修改了corsiKa的答案: Runnable带参数?

您可以在方法中声明一个类,并传递参数,如下所示:

 void Foo(String str) { class OneShotTask implements Runnable { String str; OneShotTask(String s) { str = s; } public void run() { someFunc(str); } } runOnUiThread(new OneShotTask(str)); } 

每次程序有想要显示的新Data ,您都需要更新。 您在此处列出的第二个代码是实现此目标的标准方法。 如果您继续更新线程中的Data ,可能会有一些捕获。 如果是这种情况,请考虑阻止线程,直到UI完成更新或将数据复制到另一个Data对象。

内部发生的是JVM正在复制对Data对象的引用,以便在匿名类运行时。 存储在里面的Data仍然可以更改。 如果您的方法需要对Data其他更改,请使用另一个variables(对象引用),例如: final Data finalData = data; 。 你也可以删除private Data sensordata = data; 并直接在run方法中使用数据。

它可能看起来不优雅,但这是Java将对象variables传递给匿名类的方式。 Java语言版本7中有更新的语法,但Android与Java语言版本5和6兼容。

以下是调用服务回调以更新UI状态字符串(TextView textStatus)的典型情况。 该服务可能是线程化的。

该示例结合检查是否需要线程重定向和实际重定向:

  // service callbacks public void service_StatusTextChanged(final String s) { if( isOnUiThread() ) { textStatus.setText(s); } else { runOnUiThread(new Runnable() { @Override public void run() { textStatus.setText(s); } }); } } static public boolean isOnUiThread() { return Thread.currentThread() == Looper.getMainLooper().getThread(); } 

另请参阅如何检查是否在Android中的UI线程上运行?

 public static Activity globalContext = null; CommonSetting.globalContext = this;// put this in MainACtivity.onCreate() public void createToastShort(final String message) { runOnUiThread(new Runnable() { public void run() { Toast.makeText(CommonSetting.globalContext, message, Toast.LENGTH_SHORT).show(); } }); }