每次余额发生变化时,我都会尝试更新我的余额 TextView 文本。我在一个单独的线程中调用的方法中更新了余额值,该线程是通过按按钮启动的。一旦我调用
balanceView.setText(balanceString)
,应用程序就会崩溃。在单独的线程中更新 TextView 的文本值的正确方法是什么?
private boolean working = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_work);
CreateWorkButtonListener();
}
private void CreateWorkButtonListener() {
Button workButton = findViewById(R.id.workActivityWorkButton);
workButton.setOnClickListener(
v -> StartStopWorking(workButton)
);
}
private void StartStopWorking(Button workButton) {
if (working) {
working = false;
workButton.setText(R.string.start_working);
}
else {
working = true;
workButton.setText(R.string.stop_working);
new Thread(this::StartMakingMoney).start();
}
}
private void StartMakingMoney() {
while(working) {
try {
Thread.sleep(1000);
UserInfo.balance = UserInfo.balance + 1 * UserInfo.workMultiplier;
UserInfo.totalWorkTime++;
UserInfo.CalculateWorkMultiplier();
UserInfo.SaveUserInfoToFile();
String balanceString = "$" + String.format(Locale.getDefault(), "%,.2f", UserInfo.balance);
TextView balanceView = findViewById(R.id.workActivityBalanceField);
balanceView.setText(balanceString); // THIS LINE CRASHES
}
catch (InterruptedException e) {
System.err.println("Error with sleeping for work");
}
catch (IllegalArgumentException e) {
// NO EXCEPTIONS GET CAUGHT HERE
System.err.println("Error with setting the balanceView text");
}
}
}
编辑:这是堆栈跟踪:
FATAL EXCEPTION: Thread-2
Process: com.ggz.cowsino, PID: 20926
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. Expected: main Calling: Thread-2
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:9994)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:2082)
at android.view.View.requestLayout(View.java:27043)
at android.view.View.requestLayout(View.java:27043)
at android.view.View.requestLayout(View.java:27043)
at android.view.View.requestLayout(View.java:27043)
at android.view.View.requestLayout(View.java:27043)
at android.view.View.requestLayout(View.java:27043)
at androidx.constraintlayout.widget.ConstraintLayout.requestLayout(ConstraintLayout.java:3605)
at android.view.View.requestLayout(View.java:27043)
at android.widget.TextView.checkForRelayout(TextView.java:11296)
at android.widget.TextView.setText(TextView.java:7179)
at android.widget.TextView.setText(TextView.java:6994)
at android.widget.TextView.setText(TextView.java:6946)
at com.ggz.cowsino.activities.WorkActivity.StartMakingMoney(WorkActivity.java:76)
at com.ggz.cowsino.activities.WorkActivity.$r8$lambda$yk-GWYweqGH21rtYG7QGFga2zhA(Unknown Source:0)
at com.ggz.cowsino.activities.WorkActivity$$ExternalSyntheticLambda0.run(Unknown Source:2)
我在这里找到了答案。看来你必须使用 Activity.runOnUiThread()
才能在 Android 上进行多线程时更新视图。这是我的解决方案:
runOnUiThread(() -> {
String balanceString = "$" + String.format(Locale.getDefault(), "%,.2f", UserInfo.balance);
TextView balanceView = findViewById(R.id.workActivityBalanceField);
balanceView.setText(balanceString);
});