从父级向 public void 运行() 传递参数
Passing parameters to public void run() from the parent
我有 50% 的绝望 :P。我尝试(在开始时)从线程代码更新 GUI,并得到 NullException。阅读了一段时间后,我了解到 Thread 淹没了 JavaFX 应用程序 window 为了让我从 Thread 更新 GUI,我需要使用以下代码:
Platform.runLater(new Runnable() {
@Override public void run() {
//Update UI here
for (int i=0; i<2000;i++)
{
MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
}
}
});
所以我确实使用了这段代码,它确实允许我编辑我的主要 class 的 GUI。但是,我的问题很简单。 => 这段代码,我 运行ning 来自一个线程,是一个位于 public void 运行()(线程 I 运行代码来自)。它看起来像这样:
@Override
public void run() {
String tmpVar;
... (Some code)
... (Some code)
... (Some code)
Platform.runLater(new Runnable() {
@Override public void run() {
//Update UI here
for (int i=0; i<2000;i++)
{
MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
}
}
});
... (Some code)
... (Some code)
... (Some code)
}
如何将参数从父级的 public void 运行() 传递给这个?。
例如,字符串 tmpString(我想传递给它)。
请注意,如果我在 public void 运行() 之外将其声明为静态(例如)=> 我 运行 很多线程,因此更新一个static var 可能并不总是准确的(因为很多线程会同时更新它)
谢谢!
你想做的是反对压倒一切的规则。
如果您要在 run()
方法中传递任何参数,您实际上是在重载 run()
方法,并且无论如何都不会调用它
创建新线程时,调用无参数 run()
方法。
我建议将信息存储在 static
上下文中的其他地方,然后在 run()
方法中检索它。
基本上,您需要考虑将参数传递给 Runnable
对象,而不是传递给 run()
方法。
如果将匿名 class 设为内部 class,它就变得很清楚了:
@Override
public void run() {
String tmpVar;
// ... (Some code)
// ... (Some code)
// ... (Some code)
Platform.runLater(new Updater(tmpVar));
// ... (Some code)
// ... (Some code)
// ... (Some code)
}
// ...
public static class Updater implements Runnable {
private final String var ;
public Updater(String var) {
this.var = var ;
}
@Override
public void run() {
// Access var here
for (int i=0; i<2000;i++){
MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
}
}
}
现在,如果 tmpVar
是 final
或 "effectively final1",那么它将与您的匿名内部 class 一起工作,并且基本上被翻译成完全相同的东西正如上面的内部 class (换句话说,匿名内部 class 得到一个隐式字段,该字段填充了最终变量的值):
@Override
public void run() {
final String tmpVar = ...;
// ... (Some code)
// ... (Some code)
// ... (Some code)
Platform.runLater(new Runnable() {
@Override public void run() {
// access tmpVar here:
for (int i=0; i<2000;i++)
{
MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
}
}
});
// ... (Some code)
// ... (Some code)
// ... (Some code)
}
语言设计者 可以 实际上已经用非最终变量完成了这项工作,但认为结果太混乱了。将会发生的情况是,它会被翻译成上面看到的相同的内部 class:换句话说,tmpVar
的 current 值将被隐式传递到匿名内部 class 中的一个字段。这将是一个全新的变量,具有不同的范围,与您正在访问的变量不同,它的值将是匿名内部 [=] 时 tmpVar
值的 "snapshot" 51=] 被创建。看似一个变量实际上指的是两个不同的变量 可能具有不同的值 被认为太混乱且容易出错。
但是,如果 tmpVar
不是最终的(或实际上是最终的):即您要多次为其赋值,您可以 明确地 "snapshot" 变量的值:
@Override
public void run() {
String tmpVar ;
// ... (Some code)
// ... (Some code)
// ... (Some code)
final String varCopy = tmpVar ;
Platform.runLater(new Runnable() {
@Override public void run() {
// access varCopy here:
for (int i=0; i<2000;i++)
{
MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
}
}
});
// ... (Some code)
// ... (Some code)
// ... (Some code)
}
(1) "Effectively final" 表示变量被赋值恰好一次。等价地,这意味着您可以声明它 final
而不会产生任何编译错误。
James_D 发布的一个选项是在内部 class(匿名或非匿名)中使用 final
var
其他选项,例如 new MyRunnable(someString)
或使用 Consumer<T>
您可以找到 here
您可以随时使用 getter...
public class YourClass {
private String myVar;
public void do something(String aVal) {
myVar= "Value you want to pass";
this.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d("TAG",getMyVar());
}
});
}
private String myVar(){
return myVar;
}
}
我有 50% 的绝望 :P。我尝试(在开始时)从线程代码更新 GUI,并得到 NullException。阅读了一段时间后,我了解到 Thread 淹没了 JavaFX 应用程序 window 为了让我从 Thread 更新 GUI,我需要使用以下代码:
Platform.runLater(new Runnable() {
@Override public void run() {
//Update UI here
for (int i=0; i<2000;i++)
{
MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
}
}
});
所以我确实使用了这段代码,它确实允许我编辑我的主要 class 的 GUI。但是,我的问题很简单。 => 这段代码,我 运行ning 来自一个线程,是一个位于 public void 运行()(线程 I 运行代码来自)。它看起来像这样:
@Override
public void run() {
String tmpVar;
... (Some code)
... (Some code)
... (Some code)
Platform.runLater(new Runnable() {
@Override public void run() {
//Update UI here
for (int i=0; i<2000;i++)
{
MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
}
}
});
... (Some code)
... (Some code)
... (Some code)
}
如何将参数从父级的 public void 运行() 传递给这个?。 例如,字符串 tmpString(我想传递给它)。
请注意,如果我在 public void 运行() 之外将其声明为静态(例如)=> 我 运行 很多线程,因此更新一个static var 可能并不总是准确的(因为很多线程会同时更新它)
谢谢!
你想做的是反对压倒一切的规则。
如果您要在 run()
方法中传递任何参数,您实际上是在重载 run()
方法,并且无论如何都不会调用它
创建新线程时,调用无参数 run()
方法。
我建议将信息存储在 static
上下文中的其他地方,然后在 run()
方法中检索它。
基本上,您需要考虑将参数传递给 Runnable
对象,而不是传递给 run()
方法。
如果将匿名 class 设为内部 class,它就变得很清楚了:
@Override
public void run() {
String tmpVar;
// ... (Some code)
// ... (Some code)
// ... (Some code)
Platform.runLater(new Updater(tmpVar));
// ... (Some code)
// ... (Some code)
// ... (Some code)
}
// ...
public static class Updater implements Runnable {
private final String var ;
public Updater(String var) {
this.var = var ;
}
@Override
public void run() {
// Access var here
for (int i=0; i<2000;i++){
MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
}
}
}
现在,如果 tmpVar
是 final
或 "effectively final1",那么它将与您的匿名内部 class 一起工作,并且基本上被翻译成完全相同的东西正如上面的内部 class (换句话说,匿名内部 class 得到一个隐式字段,该字段填充了最终变量的值):
@Override
public void run() {
final String tmpVar = ...;
// ... (Some code)
// ... (Some code)
// ... (Some code)
Platform.runLater(new Runnable() {
@Override public void run() {
// access tmpVar here:
for (int i=0; i<2000;i++)
{
MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
}
}
});
// ... (Some code)
// ... (Some code)
// ... (Some code)
}
语言设计者 可以 实际上已经用非最终变量完成了这项工作,但认为结果太混乱了。将会发生的情况是,它会被翻译成上面看到的相同的内部 class:换句话说,tmpVar
的 current 值将被隐式传递到匿名内部 class 中的一个字段。这将是一个全新的变量,具有不同的范围,与您正在访问的变量不同,它的值将是匿名内部 [=] 时 tmpVar
值的 "snapshot" 51=] 被创建。看似一个变量实际上指的是两个不同的变量 可能具有不同的值 被认为太混乱且容易出错。
但是,如果 tmpVar
不是最终的(或实际上是最终的):即您要多次为其赋值,您可以 明确地 "snapshot" 变量的值:
@Override
public void run() {
String tmpVar ;
// ... (Some code)
// ... (Some code)
// ... (Some code)
final String varCopy = tmpVar ;
Platform.runLater(new Runnable() {
@Override public void run() {
// access varCopy here:
for (int i=0; i<2000;i++)
{
MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
}
}
});
// ... (Some code)
// ... (Some code)
// ... (Some code)
}
(1) "Effectively final" 表示变量被赋值恰好一次。等价地,这意味着您可以声明它 final
而不会产生任何编译错误。
James_D 发布的一个选项是在内部 class(匿名或非匿名)中使用 final
var
其他选项,例如 new MyRunnable(someString)
或使用 Consumer<T>
您可以找到 here
您可以随时使用 getter...
public class YourClass {
private String myVar;
public void do something(String aVal) {
myVar= "Value you want to pass";
this.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d("TAG",getMyVar());
}
});
}
private String myVar(){
return myVar;
}
}