【问题标题】:How to change a TextView every second in Android如何在Android中每秒更改一个TextView
【发布时间】:2011-03-04 00:22:51
【问题描述】:

我制作了一个简单的 Android 音乐播放器。我想要一个 TextView 以分钟:秒格式显示歌曲中的当前时间。所以我尝试的第一件事是让活动 Runnable 并将其放在 run() 中:

int position = 0;
while (MPService.getMP() != null && position<MPService.duration) {
try {
    Thread.sleep(1000);
    position = MPService.getSongPosition();
} catch (InterruptedException e) {
    return;
}

// ... convert position to formatted minutes:seconds string ...

currentTime.setText(time); // currentTime = (TextView) findViewById(R.id.current_time);

但这失败了,因为我只能在创建它的线程中触摸 TextView。然后我尝试使用runOnUiThread(),但这不起作用,因为在主线程上重复调用Thread.sleep(1000),所以活动只是挂在一个空白屏幕上。那么有什么想法可以解决这个问题吗?


新代码:

private int startTime = 0;
private Handler timeHandler = new Handler();
private Runnable updateTime = new Runnable() {
    public void run() {
        final int start = startTime;
        int millis = appService.getSongPosition() - start;
        int seconds = (int) ((millis / 1000) % 60);
        int minutes = (int) ((millis / 1000) / 60);
        Log.d("seconds",Integer.toString(seconds)); // no problem here
        if (seconds < 10) {
            // this is hit, yet the text never changes from the original value of 0:00
            currentTime.setText(String.format("%d:0%d",minutes,seconds));
        } else {
            currentTime.setText(String.format("%d:%d",minutes,seconds));
        }
        timeHandler.postAtTime(this,(((minutes*60)+seconds+1)*1000));
    }

};

private ServiceConnection onService = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
        IBinder rawBinder) {
      appService = ((MPService.LocalBinder)rawBinder).getService();

    // start playing the song, etc. 

    if (startTime == 0) {
        startTime = appService.getSongPosition();
        timeHandler.removeCallbacks(updateTime);
        timeHandler.postDelayed(updateTime,1000);
    }
}

【问题讨论】:

    标签: android


    【解决方案1】:

    这个呢:

        int delay = 5000; // delay for 5 sec.
        int period = 1000; // repeat every sec.
    
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask()
            {
                public void run()
                {
                    //your code
                }
            }, delay, period);
    

    【讨论】:

    • 您不能通过这种方式从计时器访问 UI,它将是未定义的。您需要使用 Handler 或 Extend TimerTask,因此它会接受 UI 元素作为参数。
    【解决方案2】:

    为此使用Timer(而不是其中包含Thread.Sleepwhile 循环)。有关如何使用计时器定期更新 UI 元素的示例,请参阅本文:

    Updating the UI from a timer

    编辑:更新了返回链接,感谢Arialdohttp://web.archive.org/web/20100126090836/http://developer.android.com/intl/zh-TW/resources/articles/timed-ui-updates.html

    编辑 2:非返回链接,感谢gatoatigradohttp://android-developers.blogspot.com/2007/11/stitch-in-time.html

    【讨论】:

    • developer.android.com 是解决任何 Android 问题的好地方。 :)
    • 我知道我检查了您的答案是否正确,但我在执行此操作时遇到了麻烦...我没有遇到任何异常,似乎它应该可以正常工作,但它默默地失败了设置 TextView 的文本。如果你想看看,我已经把新代码贴在那里了。
    • 我参考了这篇文章并尝试实现,但是我使用了mHandler.postDelayed(mUpdateTimeTask, 1000);而不是 mHandler.postAtTime(this, start + (((minutes * 60) + seconds + 5) * 1000));我从另一篇博客文章(见下文)中发现了这一点,它显然提供了一个非常好的解决方案。特别是,如果您是后台服务并希望使用类似计时器的功能定期从该服务更新您的 UI。 websmithing.com/2011/02/01/…
    【解决方案3】:

    您必须使用处理程序来处理与 GUI 的交互。具体来说,线程不能触及主线程上的任何东西。您在线程中执行某些操作,如果您需要在主线程中更改某些内容,则调用处理程序并在那里执行。

    具体来说,它看起来像这样:

    Thread t = new Thread(new Runnable(){ ... do stuff here

    Handler.postMessage(); }

    然后在你的代码的其他地方,你做

    Handler h = new Handler(){

    某事某事…… 在此处修改 ui 元素 }

    想法是这样的,线程做一些事情,通知处理程序,处理程序然后接收这个消息并做一些事情,比如在 UI 线程上更新一个文本视图。

    【讨论】:

    • 只是吹毛求疵,线程不能触及主线程中的任何东西并不完全正确——SeekBars 可以被触及。但是谢谢:)
    【解决方案4】:

    这是另一个 Timer 示例,我在我的项目中使用此代码。 https://stackoverflow.com/a/18028882/1265456

    【讨论】:

      【解决方案5】:

      我认为下面的博客文章显然提供了一个非常好的解决方案。特别是,如果您是后台服务并希望使用类似计时器的功能定期从该服务更新您的 UI。 它确实对我有帮助,远远超过上面 MusiGenesis 发布的 2007 年博客链接。

      https://www.websmithing.com/2011/02/01/how-to-update-the-ui-in-an-android-activity-using-data-from-a-background-service/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-07
        • 1970-01-01
        • 2013-01-26
        • 1970-01-01
        • 2023-01-18
        • 1970-01-01
        • 1970-01-01
        • 2011-01-19
        相关资源
        最近更新 更多