Считайте на 45 секунд, сделайте паузу на 20, затем повторите с другим названием

1

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

Если у меня есть программа, которая позволит кому-то петь в течение 45 секунд, они останавливаются на 20 секунд, чтобы выпить, а затем повторить несколько песен.

Мой таймер находится в Проблема получения таймера для работы после отмены одной итерации и начала другого, но для того, чтобы это работало, когда кто-то нажимает кнопку, он запускает первый отсчет времени, но время было поставлено в очередь, и заголовок был отображен, затем, когда время будет завершено, он покажет Rest, а затем через 20 секунд отобразит новое название.

Поэтому использование sendMessageDelayed является проблемой, хотя оно работает для первой части.

В идеале я хотел бы вернуть Runnable при обратном отсчете до некоторой функции контроллера, которая затем использовала бы оператор if.

void Controller(int curCount) {
  if(curCount % 2 == 0) {
     // call thread that uses runnable with next song time limit and title
  } else {
     // call thread with 20 and "REST"
  }
}

Но это будет работать, только если

Thread t = new Thread(runnable);
... // Go to controller, which will count down
t.join();

заблокировано до завершения. Я мог бы сделать t.wait(time * 1000); вместо t.join(), но это может быть немного запоздалым или ранним, поскольку таймер не будет идеальным для поддержания времени, поэтому я не думаю, что это правильно.

Так что лучший способ сделать что-то подобное, без лишних опросов или циклов занятости.

for(SongModel m : songList) {
  countdownTime(m.getSongTime(), m.getTitle);
  countdownTime(10, "REST");
}

Edit:

Я думаю, что я не знал о проблеме с моим текущим таймером. Поскольку сообщения помещаются в очередь, они будут меняться на "Отдых", все еще отсчитывая время, оставшееся до первой песни, так как Runnable заканчивается намного быстрее, чем обработка Handler. Итак, есть недостаток в этом подходе, который заставляет меня думать, что этот дизайн с использованием sendMessageDelayed не будет работать, как я надеялся, хотя, если мне просто нужно отсчитывать один раз/кнопку, это будет хорошо, но мои потребности состоят в том, чтобы все это произошло с одним нажатием кнопки, оно запускает процесс, а затем должно имитировать цикл for в конце моего вопроса.

  • 0
    Проверьте идею ниже. Вы можете легко запросить список песен в конструкторе Listener и создать ArrayList или что угодно, что затем можно проверить в блоке if (!singing && millis >= 20000L) чтобы определить, должен ли он вызывать новый postDelayed() или просто вернись;
Теги:
timer

2 ответа

1
Лучший ответ

Здесь мы снова:)

Я написал это и протестировал его в Eclipse с эмулятором Eclair и работал нормально. Один клик рассчитывается от 54 до 0, затем от 20 до 0, затем от 45 до 0 и т.д., Пока другой клик не отменяет его. Дайте мне знать, если это соответствует вашим потребностям. Конечно, пользовательский интерфейс - это всего лишь минимальный минимум:

TimerTest.java

package com.aleadam.timertest;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class TimerTest extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button button = (Button) findViewById(R.id.btn);
        button.setOnClickListener(new MyListener ());
    }

    private class MyListener implements OnClickListener {
        private long mStartTime = 0L;
        private boolean started = false;
        private boolean singing = true;
        private final Handler mHandler = new Handler();
        private Runnable mUpdateTimeTask;
        TextView label, timer;

        public MyListener() {
            super();
            label = (TextView) findViewById (R.id.lbl);
            timer = (TextView) findViewById (R.id.timer);
        }
        public void onClick(View v) {
            if (!started) {
                started = true;
                ((Button) v).setText(R.string.button_label_stop);
                mUpdateTimeTask = new Runnable() {
                    public void run() {
                        long millis = SystemClock.elapsedRealtime() - mStartTime;
                        if (singing && millis >= 45000L) {
                            label.setText(R.string.text_label_rest);
                            mStartTime = SystemClock.uptimeMillis();
                            timer.setText("20");
                            singing = false;
                        } else if (!singing && millis >= 20000L) {
                            label.setText(R.string.text_label_sing);
                            mStartTime = SystemClock.uptimeMillis();
                            timer.setText("45");
                            singing = true;
                        } else {
                            if (singing)
                                timer.setText(Long.toString(45-millis/1000));
                            else
                                timer.setText(Long.toString(20-millis/1000));
                        }
                        mHandler.postDelayed (mUpdateTimeTask, 1000);
                    }
                };    
                singing = true;
                mStartTime = SystemClock.uptimeMillis();
                label.setText(R.string.text_label_sing);
                timer.setText("45");
                mHandler.removeCallbacks(mUpdateTimeTask);
                mHandler.postDelayed(mUpdateTimeTask, 1000);
            } else {
                started = false;
                mHandler.removeCallbacks(mUpdateTimeTask);
                label.setText("");
                timer.setText("");
                ((Button) v).setText(R.string.button_label_start);
            }
        }
    }
}

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"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/title_label"
    />
<Button
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/button_label_start"
    android:id="@+id/btn"
    />
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/lbl"
    />
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/timer"
    android:textSize="24dp"
    android:textStyle="bold" 
    android:typeface="monospace"/>
</LinearLayout>

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title_label">Timer test - 45 + 20 sec</string>
    <string name="app_name">Timer Test</string>
    <string name="button_label_start">Click to start</string>
    <string name="text_label_sing">Sing for 45 seconds</string>
    <string name="text_label_rest">20 seconds to drink!</string>
    <string name="button_label_stop">Click to cancel</string>
</resources>
  • 0
    Большое спасибо, еще раз. Это помогло мне выйти за пределы того, где я застрял. Теперь мне нужно взглянуть на то, что я взял из вашего примера, и понять, почему я не увидел такого решения.
  • 0
    Рад, что это помогло. Мне часто случается так, что я так сосредоточенно думаю о проблеме, что перечитываю одну и ту же ошибку, не замечая ее, и мне нужна свежая пара глаз, чтобы помочь мне определить ошибку.
1

Я бы сделал это с помощью Timer и пары TimerTasks.

Timer scheduler = new Timer("Song Scheduler");
TimerTask restTask = new TimerTask() {
  public void run() {
    // call rest code
    scheduler.schedule(songTask, 20*1000);      
  }
};
TimerTask songTask = new TimerTask() {
  public void run() {
    // call song code
    scheduler.schedule(restTask, 45*1000);      
  }
};

Важно то, что я не планирую следующий таймер до истечения последнего. Вы можете отрегулировать время динамически, если вы хотите, чтобы songTask продолжала длительность текущей песни (как подсказывает ваш код) или 45 секунд (как предлагает ваша проза). В любом случае, основы одинаковы.

  • 0
    У меня была та же проблема с вашим решением, что и с моим, в том, что планирование следующего таймера было проблемой.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню