Android timer

Разберем, как можно сделать в Convead виджет с таймером обратного отсчета. Выглядеть он может примерно так:

Чтобы реализовать такой таймер, нужно добавить на виджет блок <HTML>:

Теперь в этот блок нужно вставить код в зависимости от того, какой вы хотите таймер. Чаще всего наши клиенты используют один из двух таймеров:

  1. Единый таймер для всех посетителей на несколько дней в течение которых работает какая-то акция. Или «До Нового Года осталось…».
  2. Персональный таймер для каждого посетителя на несколько минут/часов в течение которых он может воспользоваться промокодом.

Ниже приведены коды для обоих вариантов:

HTML-код единого таймера до определенной даты

В коде задается дата, до которой показывается таймер обратного отсчета. Когда дата наступает, высвечивается надпись «Акция завершена». Скопируйте код таймера и вставьте его в HTML блок:

<div class=»cnv_timer» style=»text-align: center; font-size: 20px;» data-time-end=»2019-05-19 23:59:59″ data-message=»Акция завершена»></div> <script> var snv_timer = function() { var b_timer = document.querySelectorAll(‘.cnv_timer’); var d_format = function(v) { return parseInt(v) <= 9 ? ‘0’+v : v; } var update = function() { for(i=0; i < b_timer.length; i++) { var b_el = b_timer; var time_end = new Date(b_el.dataset.timeEnd.replace(/(\d+)-(\d+)-(\d+)/, ‘$2/$3/$1’)); var time_real = (new Date()); if (time_end < time_real) { b_el.innerHTML = b_el.dataset.message; } else { var s = time_end.getTime() — time_real.getTime(); s = parseInt(s / 1000); var d = parseInt(s / 86400); s -= d * 86400; var h = parseInt(s / 3600); s -= h * 3600; var m = parseInt(s / 60); s -= m * 60; b_el.innerHTML = d + ‘ д. ‘ + d_format(h) + ‘:’ + d_format(m) + ‘:’ + d_format(s); } } setTimeout(function() { if (b_timer.length > 0) update(); }, 1000); } update(); } snv_timer(); </script>

HTML-код уникального таймера для каждого посетителя

Этот таймер будет при каждом открытии начинать отсчитывать 100 секунд. Когда 100 секунд истекут, пользователь увидит надпись «Акция завершена». Скопируйте код таймера и вставьте его в HTML блок:

<div class=»cnv_timer» style=»text-align: center; font-size: 20px;» data-seconds=»100″ data-message=»Акция завершена»></div> <script> var snv_timer = function() { var b_timer = document.querySelectorAll(‘.cnv_timer’); var d_format = function(v) { return parseInt(v) <= 9 ? ‘0’+v : v; } var update = function() { for(i=0; i < b_timer.length; i++) { var b_el = b_timer; if (!b_el.dataset.current_mseconds) b_el.dataset.current_mseconds = b_el.dataset.seconds * 1000; var time_end = b_el.dataset.current_mseconds; if (time_end < 0) { b_el.innerHTML = b_el.dataset.message; } else { var s = time_end; s = parseInt(s / 1000); var d = parseInt(s / 86400); s -= d * 86400; var h = parseInt(s / 3600); s -= h * 3600; var m = parseInt(s / 60); s -= m * 60; b_el.innerHTML = d_format(h) + ‘:’ + d_format(m) + ‘:’ + d_format(s); time_end = time_end — 1000; b_el.dataset.current_mseconds = time_end; } } setTimeout(function() { if (b_timer.length > 0) update(); }, 1000); } update(); } snv_timer(); </script>

Не пугайтесь, что вместо счетчика в редакторе вы видите HTML-код. Чтобы увидеть, как выглядит счетчик – воспользуйтесь предпросмотром.

Настройка таймера

Вы можете отредактировать дату и время до которого будет работать виджет, а также подправить размер, цвет и стиль текста. Для этого потребуются базовые знания HTML и твердая рука. Стиль текста, дату и время окончания таймера можно подредактировать в самой верхней части HTML-кода:

Вы можете сделать любой таймер по аналогии с этими примерами. Ограничением тут является только ваша фантазия!

×

Читайте на здоровье!

Статья проплачена кошками — всемирно известными производителями котят.

Если статья вам понравилась, то можете поддержать проект.

Закрыть

Классы Timer и TimerTask из пакета java.util позволяют планировать запуск задания на определённое время в будущем. Вы можете создать поток, выполняющий в фоновом режиме и ожидающий заданное время. Когда время истечёт, задача, связанная с этим потоком, будет запущена. С помощью параметров можно запланировать задачу на повторяющий запуск либо на запуск по определённой дате. Вам не нужно создавать поток с помощью класса Thread, так как таймер упрощает эту задачу.

Учитывайте обстоятельство, что таймер выполняется в своём потоке и не должнен задействовать UI-элементы, которые выполняются в своём потоке. Для решения этой проблемы можете использовать метод runOnUiThread() для обновления данных у компонентов.

Классы Timer и TimerTask работают в связке. Класс Timer используется для планирования выполнения задачи. Запланированная к выполнению задача должна быть экземпляром класса TimerTask. Вы сначала создаёте объект класса TimerTask, а затем планируете его запуск с помощью класса Timer.

Класс TimerTask реализует интерфейс Runnable и может быть использован для создания потока выполнения.

В классе TimerTask имеется абстрактный метод run(), который следует переопределить. Метод должен содержать исполняемый код.

Метод cancel() прерывает задание и возвращает значение true, если выполнение задания прервано.

Метод scheduleExecutionTime() возвращает время, на которое последний раз планировался запуск задания.

Как только задача создана, она планируется для выполнения объектом класса Timer.

Методы класса Timer:

  • void cancel() — прерывает поток таймера
  • int purge() — удаляет прерванные задания из очереди таймера
  • void schedule (TimerTask task, long delay) — задание task планируется к выполнению через период в миллисекундах, переданный в параметре delay
  • void schedule (TimerTask task, long delay, long period) — задание task планируется к выполнению через период в миллисекундах, переданный в параметре delay. Затем задание повторяется повторно периодически — каждые period миллисекунд
  • void schedule (TimerTask task, Date when) — задание task планируется на время, указанное в параметре when
  • void schedule(TimerTask task, Date when, long period) — задание task планируется на время, указанное в параметре when. Затем задание выполняется повторно периодически — каждые period миллисекунд
  • void scheduleAtFixedRate (TimerTask task, long delay, long period) — задание task планируется к выполнению через период в миллисекундах, переданный в параметре delay. Затем задание выполняется повторно периодически — каждые period миллисекунд. Время каждого повтора задаётся относительно первого запуска.
  • void scheduleAtFixedRate (TimerTask task, Date when, long period) — задание task планируется к выполнению на время, указанное в параметре when. Задание затем выполняется повторно периодически — каждые period миллисекунд. Время каждого повтора задаётся относительно первого запуска.

Между методами schedule() и scheduleAtFixedRate() есть небольшая разница, которая заключается в разном поведении, которое зависит от стартовой точки запуска. Так второй метод работает как startTime + iterationNumber * delayTime и помнит время запуска. А обычный метод schedule() помнит последнее время выполнения и работает по формуле lastExecutionTime + delayTime. Для быстрых операций это не сильно отличается, а при ресурсоёмких задач разница будет заметна, например, при работе сборщика мусора приложение может притормозить и следующая задача может запуститься чуть позже.

Как только объект класса Timer создан, запуск планируется вызовом его метода schedule() и его родственника (см. выше).

Запускаем таймер

Напишем простой пример. Подготовим разметку.

<?xml version=»1.0″ encoding=»UTF-8″?> <LinearLayout xmlns:android=»http://schemas.android.com/apk/res/android» android:layout_width=»match_parent» android:layout_height=»match_parent» android:orientation=»vertical» > <CheckBox android:id=»@+id/checkBoxSingleShot» android:layout_width=»wrap_content» android:layout_height=»wrap_content» android:text=»Single Shot» /> <Button android:id=»@+id/buttonStart» android:layout_width=»match_parent» android:layout_height=»wrap_content» android:text=»Start» /> <Button android:id=»@+id/buttonCancel» android:layout_width=»match_parent» android:layout_height=»wrap_content» android:text=»Cancel» /> <TextView android:id=»@+id/textViewCounter» android:layout_width=»match_parent» android:layout_height=»wrap_content» android:textSize=»24sp» android:textStyle=»bold» /> </LinearLayout>

Будем использовать два варианта таймера — одиночное и периодическое срабатывание.

package ru.alexanderklimov.timer; // Если этот код работает, его написал Александр Климов, // а если нет, то не знаю, кто его писал. import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; public class MainActivity extends Activity { private CheckBox mSingleShotCheckBox; private Button mStartButton, mCancelButton; private TextView mCounterTextView; private Timer mTimer; private MyTimerTask mMyTimerTask; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSingleShotCheckBox = (CheckBox) findViewById(R.id.checkBoxSingleShot); mStartButton = (Button) findViewById(R.id.buttonStart); mCancelButton = (Button) findViewById(R.id.buttonCancel); mCounterTextView = (TextView) findViewById(R.id.textViewCounter); mStartButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if (mTimer != null) { mTimer.cancel(); } // re-schedule timer here // otherwise, IllegalStateException of // «TimerTask is scheduled already» // will be thrown mTimer = new Timer(); mMyTimerTask = new MyTimerTask(); if (mSingleShotCheckBox.isChecked()) { // singleshot delay 1000 ms mTimer.schedule(mMyTimerTask, 1000); } else { // delay 1000ms, repeat in 5000ms mTimer.schedule(mMyTimerTask, 1000, 5000); } } }); mCancelButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mTimer != null) { mTimer.cancel(); mTimer = null; } } }); } class MyTimerTask extends TimerTask { @Override public void run() { Calendar calendar = Calendar.getInstance(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat( «dd:MMMM:yyyy HH:mm:ss a», Locale.getDefault()); final String strDate = simpleDateFormat.format(calendar.getTime()); runOnUiThread(new Runnable() { @Override public void run() { mCounterTextView.setText(strDate); } }); } } }

Генерируем случайные показания

Допустим нам нужны ежедневные показания термометра. Но мы не можем ждать весь день при написании программ. Поэтому мы можем случайным образом создавать показания с небольшим интервалом и проверить поведение приложения.

Для удобства создадим отдельный класс-утилиту.

package ru.alexanderklimov.supercat; import java.util.Random; class Utils { private static final Random RANDOM = new Random(); static int randInt(int min, int max) { return RANDOM.nextInt((max — min) + 1) + min; } }

Создадим в классе активности метод для генерации значений и вызовем в onCreate().

package ru.alexanderklimov.supercat; // Если этот код работает, его написал Александр Климов, // а если нет, то не знаю, кто его писал. import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import java.util.Timer; import java.util.TimerTask; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setValues(); } private void setValues() { Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { final float value = Utils.randInt(-10, 35); runOnUiThread(new Runnable() { @Override public void run() { Log.i(«Info», «Value: » + value); } }); } }, 0, 3500); } }

Реклама