Java Android定时器更新文本视图(UI)

Java Android定时器更新文本视图(UI),java,android,timer,Java,Android,Timer,我在用计时器做秒表。计时器通过增加整数值来工作。然后,我希望通过不断更新textview在活动中显示此值 以下是我尝试更新活动文本视图的服务的代码: protected static void startTimer() { isTimerRunning = true; timer.scheduleAtFixedRate(new TimerTask() { public void run() { elapsedTime += 1; //in

我在用计时器做秒表。计时器通过增加整数值来工作。然后,我希望通过不断更新textview在活动中显示此值

以下是我尝试更新活动文本视图的服务的代码:

protected static void startTimer() {
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            elapsedTime += 1; //increase every sec
            StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
        }
    }, 0, 1000);
}
我在错误的线程中更新UI时出错


如何调整代码以完成不断更新textview的任务

TimerTask实现Runnable,这将使其成为一个线程。如果不做一些工作,就不能直接从其他线程更新主UI线程。
您可以使用Async Task创建计时器,并每秒发布一次更新,以更新UI。

我假设
秒表。time
是对TextView的静态或公共引用。与其这样做,不如在计时器(从单独的线程运行)和TextView之间实现通信。

您应该使用
处理程序
每X秒更新一次UI。下面是另一个显示示例的问题:

您的方法不起作用,因为您正在尝试从非UI线程更新UI。这是不允许的

protected static void startTimer() {
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            elapsedTime += 1; //increase every sec
            mHandler.obtainMessage(1).sendToTarget();
        }
    }, 0, 1000);
}

public Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
        StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
    }
};
以上代码将工作

注意:必须在主线程中创建处理程序,以便修改UI内容

StopWatch.time.post(new Runnable() {
    StopWatch.time.setText(formatIntoHHMMSS(elapsedTime));
});

此代码块基于处理程序,但您不需要创建自己的处理程序实例。

您可以使用以下实用程序:

/**
 * Created by Ofek on 19/08/2015.
 */
public class TaskScheduler extends Handler {
    private ArrayMap<Runnable,Runnable> tasks = new ArrayMap<>();
    public void scheduleAtFixedRate(final Runnable task,long delay,final long period) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                task.run();
                postDelayed(this, period);
            }
        };
        tasks.put(task, runnable);
        postDelayed(runnable, delay);
    }
    public void scheduleAtFixedRate(final Runnable task,final long period) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                task.run();
                postDelayed(this, period);
            }
        };
        tasks.put(task, runnable);
        runnable.run();
    }
    public void stop(Runnable task) {
        Runnable removed = tasks.remove(task);
        if (removed!=null) removeCallbacks(removed);
    }

}
您可以使用

此代码每隔一秒钟增加一个计数器文本视图上显示和更新计数器值

public class MainActivity extends Activity {


    private Handler handler = new Handler();
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text);
        startTimer();
    }


    int i = 0;
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            i++;
            textView.setText("counter:" + i);
            startTimer();
        }
    };

    public void startTimer() {
        handler.postDelayed(runnable, 1000);
    }

    public void cancelTimer() {
        handler.removeCallbacks(runnable);
    }

    @Override
    protected void onStop() {
        super.onStop();
        handler.removeCallbacks(runnable);
    }
}
我这样说:

String[] array = {"man", "for", "think"}; 
int j;
然后在创建时添加更多的

TextView t = findViewById(R.id.textView);

new CountDownTimer(5000,1000) {

    @Override
    public void onTick(long millisUntilFinished) {}

    @Override
    public void onFinish() {
        t.setText("I " + array[j] + " You");
        j++;
        if (j == array.length - 1) j = 0;
        start();
    }
}.start();

我不熟悉andriodapi,但是当你更新textfield constanlty时,你可能需要手动调用repaint()或者你使用的任何方法。这是一个很好的简单解决方案。不过需要做一个更正——完成处理程序定义的最后一个大括号“}”需要“;”@ArtGeigel添加了它!)@Nirav您可能需要注意的是,Handler的程序包是android.os,而不是其他程序包。分号应该在hander赋值之后,而不是现在的位置。请注意,“schedule”是“scheduleAtFixedRate”的有用替代品,适用于以下情况:,您希望在给定延迟后重复某些任务。不同之处在于,如果一次运行因其他活动而延迟(超过其请求的时间)1/2秒,则下一次运行将是延迟启动后的指定时间。当我想偶尔检查一些东西时,我会使用它,但是如果有什么事情发生了延迟,那么快速检查就没有意义了;这个答案是指OP的代码示例,其中“秒表”是OP的文本视图的名称。加上1表示桌面
String[] array = {"man", "for", "think"}; 
int j;
TextView t = findViewById(R.id.textView);

new CountDownTimer(5000,1000) {

    @Override
    public void onTick(long millisUntilFinished) {}

    @Override
    public void onFinish() {
        t.setText("I " + array[j] + " You");
        j++;
        if (j == array.length - 1) j = 0;
        start();
    }
}.start();