【问题标题】:Android/Java - CountDown Timer not workingAndroid/Java - 倒数计时器不工作
【发布时间】:2017-11-25 10:19:18
【问题描述】:

我正在制作一个计时器作为我的应用程序的一部分。我遵循了一个教程,并对程序进行了一些修改以更好地满足我的需要。但是,当我运行应用程序时,我会得到 timerTextView 的默认值(在 xml 中定义),或者只是随机数。出了什么问题?

更新:以下是活动的完整代码:

public class Main7Activity extends AppCompatActivity {




private TextView countDownText;
private CountDownTimer countDownTimer;
//private long timeLeftInMilliseconds = 1000*60*60*24*7*1;
public TextView textView3;
public TextView textView4;
public TextView textView5;
public TextView textView6;


public long timeLeftInMilliseconds;

//private int daysToGo;



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




    textView3 = (TextView) findViewById(R.id.testText);
    textView4 = (TextView) findViewById(R.id.testText2);
    textView5 = (TextView) findViewById(R.id.testText3);
    textView6 = (TextView) findViewById(R.id.testText4);






    //textView3.setText(Integer.toString(Main6Activity.progress2));


    Calendar now = Calendar.getInstance();


    textView3.setText("LMP date : " + Main6Activity.textView.getText());

    int currentDayOfYear = now.get(Calendar.DAY_OF_YEAR);



    //Day of year is the LMP date
    now.set(Calendar.DAY_OF_YEAR, Main6Activity.progress2);
    int lmpDate = now.get(Calendar.DAY_OF_YEAR);


    //Day of year is due date
    now.add(Calendar.DAY_OF_YEAR, 7*40);


    textView4.setText("Due Date: " + now.get(Calendar.DATE) + "-"
            + (now.get(Calendar.MONTH) + 1) + "-" + now.get(Calendar.YEAR));

    int dueDate = now.get(Calendar.DAY_OF_YEAR);

    if (dueDate < 365 && lmpDate > 82){
        dueDate = dueDate + (365);
    }

    if (lmpDate<82 && lmpDate>49){
        dueDate = dueDate + lmpDate;
    }



    if (lmpDate<50) {
        textView5.setText("Congratulations on Delivery");
    }

    else {

        textView5.setText(Integer.toString(dueDate));
    }
    //textView5.setText(now.getTime().toString());
    //int currentDayOfYear  = Calendar.DAY_OF_YEAR;

    int daysToGo = dueDate - currentDayOfYear;
    textView6.setText(Integer.toString(daysToGo));





    timeLeftInMilliseconds = 1000*60*60*24*daysToGo;


    countDownText = (TextView) findViewById(R.id.weeks);
    startTimer();

}



public void startTimer(){
    countDownTimer = new CountDownTimer(timeLeftInMilliseconds, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            timeLeftInMilliseconds = millisUntilFinished;
            updateTimer();
        }

        @Override
        public void onFinish() {

        }
    }.start();
}


public void updateTimer(){
    int weeks = (int) timeLeftInMilliseconds / 604800000;
    int days = (int) (timeLeftInMilliseconds % 604800000) / 86400000;
    //int hours = (int) (timeLeftInMilliseconds % 86400000) / 3600000;
    //int minutes = (int) (timeLeftInMilliseconds % 3600000) / 60000;
    int seconds = (int) (timeLeftInMilliseconds % 60000) / 1000;

    String timeLeftText;

    timeLeftText = "";
    if (weeks < 10) timeLeftText += "0";
    timeLeftText += weeks;
    timeLeftText += ":";
    if (days < 10) timeLeftText += "0";
    timeLeftText += days;
    //timeLeftText += ":";
    //if (hours < 10) timeLeftText += "0";
    //timeLeftText += hours;
    //timeLeftText += ":";
    //timeLeftText += minutes;
    //timeLeftText += ":";
    if (seconds < 10) timeLeftText += "0";
    timeLeftText += seconds;

    countDownText.setText(timeLeftText);
}



public void editInfo(View v){

    Intent intent = new Intent(Main7Activity.this, Main6Activity.class);
    startActivity(intent);

}

}

我还需要计时器在后台运行。这段代码会这样做吗?

谢谢。

【问题讨论】:

  • 你能发布完整的活动代码吗?
  • 确保您的 countDownText.setText(timeLeftText) 在主线程上运行。我认为如果您尝试从后台线程更新 ui 项目,它实际上不会更新 ui。我看不到你在哪里运行你的计时器类,所以我不确定是否是这种情况。

标签: java android time countdown countdowntimer


【解决方案1】:

尝试声明这些变量:

    Handler countHandler ;
    Runnable countRunnable ;
    private final long INTERVAL = 1000 ; // this the interval period which the timer will be triggered each time

然后像这样改变你的方法:

public void startTimer(){
        countHandler = new Handler() ;
        countRunnable = new Runnable() {
            @Override
            public void run() {
                updateTimer();

                timeLeftInMilliseconds= timeLeftInMilliseconds - INTERVAL ;

                if(timeLeftInMilliseconds>=0){
                    countHandler.postDelayed(this, INTERVAL) ;
                } else {
                    cancelTimer(); // here timer is finished
                }
            }
        } ;
        countHandler.post(countRunnable) ;
    }

    public void cancelTimer(){
        countHandler.removeCallbacks(countRunnable);
    }

【讨论】:

    【解决方案2】:

    试试下面的代码。

    Timer_Service.java

    import android.app.Service;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.os.Handler;
    import android.os.IBinder;
    import android.preference.PreferenceManager;
    import android.support.annotation.Nullable;
    import android.util.Log;
    
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.TimeUnit;
    
    
    public class Timer_Service extends Service {
    
        public static String str_receiver = "your_package_name.receiver";
    
        private Handler mHandler = new Handler();
        Calendar calendar;
        SimpleDateFormat simpleDateFormat;
        String strDate;
        Date date_current, date_diff;
        SharedPreferences mpref;
        SharedPreferences.Editor mEditor;
    
        private Timer mTimer = null;
        public static final long NOTIFY_INTERVAL = 1000;
        Intent intent;
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            mpref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
            mEditor = mpref.edit();
            calendar = Calendar.getInstance();
            simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
    
            mTimer = new Timer();
            mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 5, NOTIFY_INTERVAL);
            intent = new Intent(str_receiver);
        }
    
    
        class TimeDisplayTimerTask extends TimerTask {
    
            @Override
            public void run() {
                mHandler.post(new Runnable() {
    
                    @Override
                    public void run() {
    
                        calendar = Calendar.getInstance();
                        simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
                        strDate = simpleDateFormat.format(calendar.getTime());
                        Log.e("strDate", strDate);
                        twoDatesBetweenTime();
                    }
                });
            }
        }
    
        public String twoDatesBetweenTime() {
    
            try {
                date_current = simpleDateFormat.parse(strDate);
            } catch (Exception e) {
    
            }
    
            try {
                date_diff = simpleDateFormat.parse(mpref.getString("data", ""));
            } catch (Exception e) {
    
            }
    
            try {
                long diff = date_current.getTime() - date_diff.getTime();
                int int_hours = Integer.valueOf(mpref.getString("hours", ""));
    
                long int_timer = TimeUnit.HOURS.toMillis(int_hours);
                long long_hours = int_timer - diff;
                long diffSeconds2 = long_hours / 1000 % 60;
                long diffMinutes2 = long_hours / (60 * 1000) % 60;
                long diffHours2 = long_hours / (60 * 60 * 1000) % 24;
    
    
                if (long_hours > 0) {
                    String str_testing = diffHours2 + ":" + diffMinutes2 + ":" + diffSeconds2;
    
                    Log.e("TIME", str_testing);
    
                    fn_update(str_testing);
                } else {
                    mEditor.putBoolean("finish", true).commit();
                    mTimer.cancel();
                }
            } catch (Exception e) {
                mTimer.cancel();
                mTimer.purge();
            }
    
            return "";
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.e("Service finish", "Finish");
        }
    
        private void fn_update(String str_time) {
    
            intent.putExtra("time", str_time);
            sendBroadcast(intent);
        }
    }
    

    您的 Timer.java 活动:

    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.SharedPreferences;
    import android.os.Bundle;
    import android.preference.PreferenceManager;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    
    
    public class Timer extends AppCompatActivity implements View.OnClickListener {
    
        private Button btn_start, btn_cancel;
        private TextView tv_timer;
        String date_time;
        Calendar calendar;
        SimpleDateFormat simpleDateFormat;
        EditText et_hours;
    
        SharedPreferences mpref;
        SharedPreferences.Editor mEditor;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_timer);
            init();
        }
    
        private void init() {
            btn_start = (Button) findViewById(R.id.btn_timer);
            tv_timer = (TextView) findViewById(R.id.tv_timer);
            et_hours = (EditText) findViewById(R.id.et_hours);
            btn_cancel = (Button) findViewById(R.id.btn_cancel);
    
            btn_start.setOnClickListener(this);
            btn_cancel.setOnClickListener(this);
    
            mpref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
            mEditor = mpref.edit();
    
            try {
                String str_value = mpref.getString("data", "");
                if (str_value.matches("")) {
                    et_hours.setEnabled(true);
                    btn_start.setEnabled(true);
                    tv_timer.setText("");
    
                } else {
    
                    if (mpref.getBoolean("finish", false)) {
                        et_hours.setEnabled(true);
                        btn_start.setEnabled(true);
                        tv_timer.setText("");
                    } else {
    
                        et_hours.setEnabled(false);
                        btn_start.setEnabled(false);
                        tv_timer.setText(str_value);
                    }
                }
            } catch (Exception e) {
    
            }
        }
    
        @Override
        public void onClick(View v) {
    
            switch (v.getId()) {
                case R.id.btn_timer:
    
    
                    if (et_hours.getText().toString().length() > 0) {
    
                        int int_hours = Integer.valueOf(et_hours.getText().toString());
    
                        if (int_hours <= 24) {
    
    
                            et_hours.setEnabled(false);
                            btn_start.setEnabled(false);
    
    
                            calendar = Calendar.getInstance();
                            simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
                            date_time = simpleDateFormat.format(calendar.getTime());
    
                            mEditor.putString("data", date_time).commit();
                            mEditor.putString("hours", et_hours.getText().toString()).commit();
    
    
                            Intent intent_service = new Intent(getApplicationContext(), Timer_Service.class);
                            startService(intent_service);
                        } else {
                            Toast.makeText(getApplicationContext(), "Please select the value below 24 hours", Toast.LENGTH_SHORT).show();
                        }
    /*
                        mTimer = new Timer();
                        mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 5, NOTIFY_INTERVAL);*/
                    } else {
                        Toast.makeText(getApplicationContext(), "Please select value", Toast.LENGTH_SHORT).show();
                    }
                    break;
    
    
                case R.id.btn_cancel:
    
    
                    Intent intent = new Intent(getApplicationContext(), Timer_Service.class);
                    stopService(intent);
    
                    mEditor.clear().commit();
    
                    et_hours.setEnabled(true);
                    btn_start.setEnabled(true);
                    tv_timer.setText("");
    
                    break;
            }
        }
    
        private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String str_time = intent.getStringExtra("time");
                tv_timer.setText(str_time);
            }
        };
    
        @Override
        protected void onResume() {
            super.onResume();
            registerReceiver(broadcastReceiver, new IntentFilter(Timer_Service.str_receiver));
    
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            unregisterReceiver(broadcastReceiver);
        }
    }
    

    您的 activity_timer.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <EditText
            android:id="@+id/et_hours"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:hint="Hours"
            android:inputType="time" />
    
    
        <Button
            android:id="@+id/btn_timer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_above="@+id/btn_cancel"
            android:text="Start Timer" />
    
        <Button
            android:id="@+id/btn_cancel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:text="cancel timer" />
    
    
        <TextView
            android:id="@+id/tv_timer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="00:00:00"
            android:textColor="#000000"
            android:textSize="25dp" />
    
    </RelativeLayout>
    

    资源参考:this link

    您需要根据您的要求进行一些修改。即使您关闭应用程序,倒计时仍会继续。

    【讨论】:

    • 感谢您的帮助,但我不想只制作一个完整的计时器应用程序。这是我的应用程序的一个活动部分,必须在创建活动时自动执行。
    • @BLLRoy 你到底想达到什么目的?您希望 countDown Timer 在后台运行,直到您的应用程序正在运行,或者您希望它即使在您的应用程序关闭时也能运行。
    • 即使应用程序关闭,计时器也应该运行。但是,您提出的代码具有启动和停止按钮。我需要代码自动执行。原始帖子/问题中的代码有一个名为 daysToGo 的变量。倒计时计时器应该从当前日期开始倒计时到那些天。 daysToGo 每天减少 1。但是,我发布的代码不起作用。当代码运行时,我得到随机值或倒计时文本视图的默认值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多