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

时间:2023-02-08 22:16:27

I'm using a timer to create a stop watch. The timer works by increasing a integer value. I want to then display this value in the activity by constantly updating a textview.

我正在使用计时器来制作秒表。计时器通过增加整数值来工作。我想通过不断更新textview在活动中显示此值。

Here's my code from the service where I try and update the activity's textview:

这是我尝试更新活动的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);
}

I got some kind of error about updating the UI in the wrong thread.

我在错误的线程中更新UI时遇到了一些错误。

How can I adapt my code to accomplish this task of constantly updating the textview?

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

8 个解决方案

#1


86  

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
    }
};

Above code will work...

上面的代码将起作用......

Note: Handlers must be created in your main thread so that you can modify UI content.

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

#2


8  

You should use Handler instead to update UI every X seconds. Here is another question that show an example: Repeat a task with a time delay?

您应该使用Handler来每隔X秒更新一次UI。这是另一个显示示例的问题:重复一个延迟时间的任务?

Your approach doesn't work because you are trying to update UI from non-UI thread. This is not allowed.

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

#3


6  

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

this code block is based on Handler but you don't need to create your own Handler instance.

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

#4


2  

TimerTask implements Runnable, which would make it a thread. You can not update the main UI thread directly from a different thread without some work. One thing you could do is use Async Task to create the timer and publish an update every second that will update the UI.

TimerTask实现了Runnable,这将使它成为一个线程。如果没有一些工作,您无法直接从其他线程更新主UI线程。您可以做的一件事是使用Async Task创建计时器并每秒发布一次更新UI的更新。

#5


2  

I'm assuming StopWatch.time is some static or public reference to your TextView. Instead of doing this, you should implement a BroadcastReceiver to communicate between your timer (which runs from a separate thread) and your TextView.

我假设StopWatch.time是对TextView的一些静态或公共引用。您应该实现BroadcastReceiver,以便在计时器(从单独的线程运行)和TextView之间进行通信,而不是这样做。

#6


2  

You can use the following utility :

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

/**
 * 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);
    }

}

Then anywhere in code that runs by the UI Thread you can use it simply like this:

然后在UI线程运行的代码中的任何地方,您都可以像这样使用它:

TaskScheduler timer = new TaskScheduler();
        timer.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                time.setText(simpleDateFormat.format(GamePlay.instance().getLevelTime()));
            }
        },1000);

#7


1  

you can use Handler.

你可以使用Handler。

this code increase a counter every one second and show and update counter value on a textView.

此代码每隔一秒增加一个计数器,并在textView上显示和更新计数器值。

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);
    }
}

#8


-3  

 timer.schedule(new TimerTask() {
            @Override
            public void run() {

                //your actions

            }
        },1*1000);//1 sec

#1


86  

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
    }
};

Above code will work...

上面的代码将起作用......

Note: Handlers must be created in your main thread so that you can modify UI content.

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

#2


8  

You should use Handler instead to update UI every X seconds. Here is another question that show an example: Repeat a task with a time delay?

您应该使用Handler来每隔X秒更新一次UI。这是另一个显示示例的问题:重复一个延迟时间的任务?

Your approach doesn't work because you are trying to update UI from non-UI thread. This is not allowed.

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

#3


6  

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

this code block is based on Handler but you don't need to create your own Handler instance.

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

#4


2  

TimerTask implements Runnable, which would make it a thread. You can not update the main UI thread directly from a different thread without some work. One thing you could do is use Async Task to create the timer and publish an update every second that will update the UI.

TimerTask实现了Runnable,这将使它成为一个线程。如果没有一些工作,您无法直接从其他线程更新主UI线程。您可以做的一件事是使用Async Task创建计时器并每秒发布一次更新UI的更新。

#5


2  

I'm assuming StopWatch.time is some static or public reference to your TextView. Instead of doing this, you should implement a BroadcastReceiver to communicate between your timer (which runs from a separate thread) and your TextView.

我假设StopWatch.time是对TextView的一些静态或公共引用。您应该实现BroadcastReceiver,以便在计时器(从单独的线程运行)和TextView之间进行通信,而不是这样做。

#6


2  

You can use the following utility :

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

/**
 * 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);
    }

}

Then anywhere in code that runs by the UI Thread you can use it simply like this:

然后在UI线程运行的代码中的任何地方,您都可以像这样使用它:

TaskScheduler timer = new TaskScheduler();
        timer.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                time.setText(simpleDateFormat.format(GamePlay.instance().getLevelTime()));
            }
        },1000);

#7


1  

you can use Handler.

你可以使用Handler。

this code increase a counter every one second and show and update counter value on a textView.

此代码每隔一秒增加一个计数器,并在textView上显示和更新计数器值。

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);
    }
}

#8


-3  

 timer.schedule(new TimerTask() {
            @Override
            public void run() {

                //your actions

            }
        },1*1000);//1 sec