java - 带有 scheduleAtFixedRate 的 Timer 和 TimerTask 在更新 TextView 时导致 CalledFromWrongThreadException 崩溃

标签 java android timer

我是 Android 编程新手。现在,我想以指定的时间间隔更新 Activity 中的 TextView 值。

汽车类:

public class Car {
    public int Speed;
    public int RPM;
    public int Distance;
    public int Fuel;

    public Car(int Speed, int RPM, int Distance, int Fuel) {
        System.out.println(
                "Inisialisasi Baru"+
                    "\nSpeed: "+ Speed +
                    "\nRPM: "+ RPM +
                    "\nDistance: "+ Distance +
                    "\nFuel: "+ Fuel
        );
        this.Speed = Speed;
        this.RPM = RPM;
        this.Distance = Distance;
        this.Fuel = Fuel;
    }

    public int getSpeed() {
        return Speed;
    }
    public int getRPM() {
        return RPM;
    }
    public int getDistance() {
        return Distance;
    }
    public int getFuel() {
        return Fuel;
    }
}

Activity java:

TextView carSpeed, carRPM, carDistance, carFuel;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_mock);

    carSpeed = (TextView) findViewById(R.id.carSpeed);
    carRPM = (TextView) findViewById(R.id.carRPM);
    carDistance = (TextView) findViewById(R.id.carDistance);
    carFuel = (TextView) findViewById(R.id.carFuel);

    new Timer().scheduleAtFixedRate(new TimerTask(){
        Car car = new Car(20, 20, 20, 5);
        @Override
        public void run(){
            int maxSpeed = car.Speed + 5;
            int minSpeed = car.Speed - 4;
            int maxRPM = car.RPM + 5;
            int minRPM = car.RPM - 4;
            car.Speed = new Random().nextInt((maxSpeed - minSpeed) + 1) + minSpeed;
            car.RPM = new Random().nextInt((maxRPM - minRPM) + 1) + minRPM;
            car.Distance += 1;
            car.Fuel -= 1;
            if (car.Fuel <= 0) {
                car.Fuel += 20;
            }
            if (car.Speed <= 0) {
                car.Speed = 20;
            } else if (car.Speed >= 150) {
                car.Speed -= 50;
            }
            carSpeed.setText(Integer.toString(car.getSpeed()) + " km/h");
            carRPM.setText(Integer.toString(car.getRPM()) + " rpm");
            carDistance.setText(Integer.toString(car.getDistance()) + " km");
            carFuel.setText(Integer.toString(car.getFuel()) + " l");
        }
    },0,5000);
}

我认为问题的发生是因为我试图在新的 Timer()setText 并且这导致应用程序关闭。谢谢。

最佳答案

是的,您的直觉是正确的。出现问题是因为 View 正在从计时器更新。

错误将类似于:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

在 Android 中, View 只能从“UI 线程”(通常称为“主线程”)进行更新。

这里的问题是Runnable的run()方法是在一个单独的线程中执行的。

更新可以在 Activity 的主线程上完成,如下所示:

...
runOnUiThread(new Runnable() {
    @Override 
    public void run() {
        // Do all your view updates in here
        textView.setText("string");
    }
});
....

我看不到你代码的上下文,但如果它是一个 fragment : getActivity().runOnUiThread(...);

切换到主线程还有其他方法。您可能还想研究 AsyncTask 和 Handlers。

关于java - 带有 scheduleAtFixedRate 的 Timer 和 TimerTask 在更新 TextView 时导致 CalledFromWrongThreadException 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49829326/

相关文章:

c++ - 在 C++ 11 中保持分离线程有什么坏处

javascript - 在 Angular.js 中显示多个计时器功能

android - 从 android 或 iOS 将参数传递给 flutter 模块

java - 将实例化对象修改为实例化对象

java - 如何制作 GridView 项目( TextView )的 .setText() onItemSelected?

java - 使用 JSOUP 解析动态加载(通过滚动)页面

android - 删除选定行后的 ListView 动画行

java - 线程退出后调用回调 - Android

java - 计时器未更新方法无法正常工作

java - Java 中排序和删除重复项的最佳数据集是什么?