繁体   English   中英

Android CountDownTimer中的.cancel()问题

[英]Problems with .cancel() in Android CountDownTimer

我有Android CountDownTimer的问题。

我正在尝试学习一些JAVA / Android,并开始使用一个简单的应用程序供我自己在煮咖啡时使用。 我无法获得CountDown Timer的.cancel ()函数。 我在这个论坛和其他论坛上看过几个主题。

我的Java代码:

package jandidrik.kaffe;

import android.content.Context;
import android.os.CountDownTimer;
import android.os.Vibrator;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.view.View;
import android.widget.Toast;

import java.util.concurrent.TimeUnit;


public class MainActivity extends AppCompatActivity implements OnSeekBarChangeListener {

private SeekBar WaterSeekBar, CoffeeSeekBar, BloomingSeekBar, BrewingSeekBar;
private TextView WaterText, CoffeeText, BloomingText, BrewingText, TimerText;

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

    WaterSeekBar = (SeekBar) findViewById(R.id.WaterSeekBar);
    CoffeeSeekBar = (SeekBar) findViewById(R.id.CoffeeSeekBar);
    BloomingSeekBar = (SeekBar) findViewById(R.id.BloomingSeekBar);
    BrewingSeekBar = (SeekBar) findViewById(R.id.BrewingSeekBar);

    WaterText = (TextView) findViewById(R.id.WaterText);
    CoffeeText = (TextView) findViewById(R.id.CoffeeText);
    BloomingText = (TextView) findViewById(R.id.BloomingText);
    BrewingText = (TextView) findViewById(R.id.BrewingText);
    TimerText = (TextView) findViewById(R.id.Timer);

    WaterSeekBar.setOnSeekBarChangeListener(this);
    CoffeeSeekBar.setOnSeekBarChangeListener(this);
    BloomingSeekBar.setOnSeekBarChangeListener(this);
    BrewingSeekBar.setOnSeekBarChangeListener(this);

    WaterSeekBar.setProgress(1000);
    WaterText.setText(Integer.toString(WaterSeekBar.getProgress()));
    CoffeeSeekBar.setProgress(63);
    CoffeeText.setText(Integer.toString(CoffeeSeekBar.getProgress()));

    Long Minutes = TimeUnit.SECONDS.toMinutes(BrewingSeekBar.getProgress());
    Long Seconds = BrewingSeekBar.getProgress() - TimeUnit.MINUTES.toSeconds(Minutes);
    BrewingText.setText("" + String.format("%01d:%02d", Minutes, Seconds));
}

@Override
public void onProgressChanged(SeekBar Bar, int progress, boolean fromUser) {
    switch (Bar.getId()) {
        case R.id.WaterSeekBar:
            WaterText.setText(Integer.toString(progress));
            break;
        case R.id.CoffeeSeekBar:
            CoffeeText.setText(Integer.toString(progress));
            break;
        case R.id.BloomingSeekBar:
            BloomingText.setText(Integer.toString(progress));
            break;
        case R.id.BrewingSeekBar:
            Long Minutes = TimeUnit.SECONDS.toMinutes(BrewingSeekBar.getProgress());
            Long Seconds = BrewingSeekBar.getProgress() - TimeUnit.MINUTES.toSeconds(Minutes);
            BrewingText.setText("" + String.format("%01d:%02d", Minutes, Seconds));
            break;
    }
}

@Override
public void onStartTrackingTouch(SeekBar Bar) {
}

@Override
public void onStopTrackingTouch(SeekBar Bar) {
}

public void Brew(View V) {

    final Button BrewButton = (Button) V;
    final String ButtonText = BrewButton.getText().toString();

    CountDownTimer Count = new CountDownTimer(BrewingSeekBar.getProgress() * 1000, 1000) {

        @Override
        public void onTick(long millisUntilFinished) {
            Long Minutes = TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished);
            Long Seconds = TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(Minutes);

            TimerText.setText("" + String.format("%01d:%02d", Minutes, Seconds));

            int VibrateTime = BrewingSeekBar.getProgress() - BloomingSeekBar.getProgress();

            if ((TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished)) == VibrateTime) {
                Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                // Vibrate 500ms
                v.vibrate(500);

                Toast.makeText(MainActivity.this, "Blooming is finnished!", Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onFinish() {
            TimerText.setText("Finished!");
        }
    };

    if (ButtonText.equals("Start Brewing!")) {
        Count.start();
        BrewButton.setText("Stop Timer!");
    } else {
        Count.cancel();
        BrewButton.setText("Start Brewing!");
    }
}
}

我的XML代码:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:keepScreenOn="true">
tools:context="jandidrik.kaffe.MainActivity">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Adjust Amount of water (ml)"
    android:layout_marginBottom="8dp"
    android:layout_marginTop="16dp"
    />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<SeekBar
    android:id="@+id/WaterSeekBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:max="1200"
    android:progress="1000"
    android:layout_weight="2"
    />

<TextView
    android:id="@+id/WaterText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="14"
    android:text="1000"
    android:layout_marginLeft="8dp"
    />

</LinearLayout>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Adjust Amount of coffee (g)"
    android:layout_marginBottom="8dp"
    android:layout_marginTop="8dp"
    />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

<SeekBar
    android:id="@+id/CoffeeSeekBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:max="100"
    android:progress="63"
    android:layout_weight="2"
    />

    <TextView
        android:id="@+id/CoffeeText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="63"
        android:layout_weight="14"
        android:layout_marginLeft="8dp"
        />

</LinearLayout>

<TextView
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:background="@android:color/darker_gray"
    android:layout_marginTop="52dp"
    android:layout_marginBottom="52dp"
    />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Set the blooming time (s)"
    android:layout_marginBottom="8dp"
    />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <SeekBar
        android:id="@+id/BloomingSeekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="60"
        android:progress="30"
        android:layout_weight="2"
        />

    <TextView
        android:id="@+id/BloomingText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="30"
        android:layout_weight="14"
        android:layout_marginLeft="8dp"
        />

</LinearLayout>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Set the total brewing time (m:ss("
    android:layout_marginBottom="8dp"
    android:layout_marginTop="8dp"
    />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <SeekBar
        android:id="@+id/BrewingSeekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="480"
        android:progress="240"
        android:layout_weight="2"
        />

    <TextView
        android:id="@+id/BrewingText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="4 min 0 s"
        android:layout_weight="14"
        android:layout_marginLeft="8dp"
        />

</LinearLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

<Button
    android:id="@+id/BrewButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Start Brewing!"
    android:layout_centerInParent="true"
    android:layout_marginTop="16dp"
    android:layout_marginBottom="16dp"
    android:onClick="Brew"

    />

</RelativeLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

<Chronometer
    android:id="@+id/Timer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="30sp"
    android:format="%s:%s"
    android:layout_centerInParent="true"
    />
</RelativeLayout>

</LinearLayout>

您正试图阻止CountDownTimer错误实例。 修复代码的最简单方法就是将Count移出方法。

private CountDownTimer currentCount;
public void Brew(View v) {
    final Button BrewButton = (Button) V;
    final String ButtonText = BrewButton.getText().toString();

    if (ButtonText.equals("Stop Timer!") && currentCount != null) {
        currentCount.cancel();
        currentCount = null;
        BrewButton.setText("Start Brewing!");
        return;
    }

    currentCount = new CountDownTimer(BrewingSeekBar.getProgress() * 1000, 1000) {

        @Override
        public void onTick(long millisUntilFinished) {
            Long Minutes = TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished);
            Long Seconds = TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(Minutes);

            TimerText.setText("" + String.format("%01d:%02d", Minutes, Seconds));

            int VibrateTime = BrewingSeekBar.getProgress() - BloomingSeekBar.getProgress();

            if ((TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished)) == VibrateTime) {
                Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                // Vibrate 500ms
                v.vibrate(500);

                Toast.makeText(MainActivity.this, "Blooming is finnished!", Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onFinish() {
            TimerText.setText("Finished!");
        }
    };

    currentCount.start();
    BrewButton.setText("Stop Timer!");
}

每次单击BrewButton时,将调用Brew()方法,将分配另一个“new”CountDownTimer并将其分配给Count变量。 无论是否将此变量声明移出Brew方法的范围,都不会改变它。 因此,可能会在不正确的CountDownTimer对象上调用.cancel()

您的程序对原始CountDownTimer对象的引用会丢失,但它仍然在运行,直到它被垃圾收集并仍然会调用它的.onTick()和.inFinish()方法。

解决方案是确保您只挂在一个CountDownTimer对象上,并确保在用户第二次按下BrewButton以停止计时时引用该对象(而不是分配新对象)。

也许你会将Count放入类范围,初始化为NULL,然后只有当Count为NULL时才在Brew()方法中实例化一个新的。 然后,在if (StartBrewing)语句中,确保在调用Count.cancel()后将Count重置为NULL

我会留下准确的代码,作为读者练习。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM