如何在线程内设置TextView文本?

问题描述 投票:0回答:1

每次余额发生变化时,我都会尝试更新我的余额 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)
java android multithreading asynchronous
1个回答
0
投票

我在这里找到了答案。看来你必须使用 Activity.runOnUiThread()

 才能在 Android 上进行多线程时更新视图。这是我的解决方案:

runOnUiThread(() -> { String balanceString = "$" + String.format(Locale.getDefault(), "%,.2f", UserInfo.balance); TextView balanceView = findViewById(R.id.workActivityBalanceField); balanceView.setText(balanceString); });
    
© www.soinside.com 2019 - 2024. All rights reserved.