当前位置: 首页 > 面试题库 >

Android:CountDownTimer跳过最后一个onTick()!

方宏富
2023-03-14
问题内容

码:

public class SMH extends Activity {

    public void onCreate(Bundle b) {  
        super.onCreate(b);  
        setContentView(R.layout.main);

        TextView tv = (TextView) findViewById(R.id.tv);

        new CountDownTimer(10000, 2000) {  
            public void onTick(long m) {  
               long sec = m/1000+1;  
               tv.append(sec+" seconds remain\n");  
            }  
            public void onFinish() {  
               tv.append("Done!");  
            }  
        }.start();  
   }

输出:
剩余10秒剩余
8秒剩余
6秒剩余
4秒剩余
完成!

问题:

如何显示“ 剩余2秒 ”?经过的时间确实是10秒,但是最后一个onTick()永远不会发生。如果我将第二个参数从2000更改为1000,则输出为:

剩余10秒剩余
9秒剩余
8秒剩余
7秒剩余
6秒剩余
5秒剩余
4秒剩余
3秒剩余
2秒剩余
完成!

如此看来,似乎跳过了最后一个onTick()调用。顺便说一句,XML文件基本上是默认的main.xml,其中TextView分配了ID tv
,文本设置为“”。


问题答案:

我不知道为什么最后一个刻度不起作用,但是例如可以使用Runable创建自己的计时器。

class MyCountDownTimer {
    private long millisInFuture;
    private long countDownInterval;
    public MyCountDownTimer(long pMillisInFuture, long pCountDownInterval) {
            this.millisInFuture = pMillisInFuture;
            this.countDownInterval = pCountDownInterval;
        }
    public void Start() 
    {
        final Handler handler = new Handler();
        Log.v("status", "starting");
        final Runnable counter = new Runnable(){

            public void run(){
                if(millisInFuture <= 0) {
                    Log.v("status", "done");
                } else {
                    long sec = millisInFuture/1000;
                    Log.v("status", Long.toString(sec) + " seconds remain");
                    millisInFuture -= countDownInterval;
                    handler.postDelayed(this, countDownInterval);
                }
            }
        };

        handler.postDelayed(counter, countDownInterval);
    }
}

然后开始

new MyCountDownTimer(10000, 2000).Start();

编辑高飞的问题

您应该有一个变量来保存计数器状态(布尔值)。那么您可以编写Stop()方法,例如Start()。

编辑2高飞的问题

实际上,没有停止计数器的错误,但是在stop(resume)之后再次启动时存在错误。

我正在写一个刚刚尝试过的新的更新的完整代码,它正在工作。这是一个基本的计数器,带有“开始”和“停止”按钮在屏幕上显示时间。

柜台类

public class MyCountDownTimer {
    private long millisInFuture;
    private long countDownInterval;
    private boolean status;
    public MyCountDownTimer(long pMillisInFuture, long pCountDownInterval) {
            this.millisInFuture = pMillisInFuture;
            this.countDownInterval = pCountDownInterval;
            status = false;
            Initialize();
    }

    public void Stop() {
        status = false;
    }

    public long getCurrentTime() {
        return millisInFuture;
    }

    public void Start() {
        status = true;
    }
    public void Initialize() 
    {
        final Handler handler = new Handler();
        Log.v("status", "starting");
        final Runnable counter = new Runnable(){

            public void run(){
                long sec = millisInFuture/1000;
                if(status) {
                    if(millisInFuture <= 0) {
                        Log.v("status", "done");
                    } else {
                        Log.v("status", Long.toString(sec) + " seconds remain");
                        millisInFuture -= countDownInterval;
                        handler.postDelayed(this, countDownInterval);
                    }
                } else {
                    Log.v("status", Long.toString(sec) + " seconds remain and timer has stopped!");
                    handler.postDelayed(this, countDownInterval);
                }
            }
        };

        handler.postDelayed(counter, countDownInterval);
    }
}

活动课

public class CounterActivity extends Activity {
    /** Called when the activity is first created. */
    TextView timeText;
    Button startBut;
    Button stopBut;
    MyCountDownTimer mycounter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        timeText = (TextView) findViewById(R.id.time);
        startBut = (Button) findViewById(R.id.start);
        stopBut = (Button) findViewById(R.id.stop);
        mycounter = new MyCountDownTimer(20000, 1000);
        RefreshTimer();
    }

    public void StartTimer(View v) {
        Log.v("startbutton", "saymaya basladi");
        mycounter.Start();
    }

    public void StopTimer(View v) {
        Log.v("stopbutton", "durdu");
        mycounter.Stop();
    }

    public void RefreshTimer() 
    {
        final Handler handler = new Handler();
        final Runnable counter = new Runnable(){

            public void run(){
                timeText.setText(Long.toString(mycounter.getCurrentTime()));
                handler.postDelayed(this, 100);
            }
        };

        handler.postDelayed(counter, 100);
    }
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:weightSum="1">
    <TextView android:textAppearance="?android:attr/textAppearanceLarge" 
              android:text="TextView" android:layout_height="wrap_content" 
              android:layout_width="wrap_content" 
              android:id="@+id/time">
    </TextView>
    <Button android:text="Start" 
            android:id="@+id/start" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:onClick="StartTimer">
    </Button>
    <Button android:text="Stop" 
            android:id="@+id/stop" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:onClick="StopTimer">
    </Button>
</LinearLayout>


 类似资料:
  • 如果我有一个<代码>流 最明显的解决方案是使用<code>limit(originalLength-elementsToRemoveAtEnd),但这需要事先知道初始长度,这并不总是如此。 有没有一种方法可以删除长度未知的流的最后几个元素,而无需将其收集到中,计算元素并再次流式传输?

  • 我有一个以下格式的文件: 姓名:John 文本:Hello --空行--缓冲读取器正在阅读此内容 名称:Adam 文本:Hi --空行--缓冲读取器正在跳过此行 我尝试了多种方法来读取最后一行空行,但都不起作用。有什么建议吗?我有一个程序可以验证消息的格式是否正确。正确的格式应该有三行,第一行是名称,第二行是文本,第二行是空行。由于BufferedReader没有读取最后一个空行,我的程序总是说消

  • 兔子最多能跳50厘米远。它想穿越到河的另一边,但它不会游泳。所以唯一的希望是跳到河上的岩石上,这些岩石位于一条直线上。岩石的位置从开始位置开始测量,假设兔子从0厘米标记开始。对岸可以被视为一块大石头。它是岩石组中的最后一块岩石。 例如,岩石位于位置32, 46, 70, 85, 96, 123,而对面的河岸位于位置145。对于上面的例子,它需要进行3次跳跃,在岩石0(起点)、岩石46和岩石96到达

  • 我想在和之间进行映射,但不包括一个字段,例如。我如何才能做到这一点,因为我认为这种方法会起作用,但它没有:

  • 最后一个例子是addTime: Time addTime2 (const Time& t1, const Time& t2) { double seconds = convertToSeconds (t1) + convertToSeconds (t2); return makeTime (seconds); } 我们要对该函数做一些改变,包括: 把函数名addTime改成Time: