2011-04-26 38 views
1

在試圖限制電池使用情況時,我不需要有繁忙的循環,所以我不確定如何解決這個問題。計數45秒,暫停20秒,然後重複不同的標題

如果我有一個讓人唱歌45秒的節目,然後他們暫停20秒喝一杯,然後重複一些歌曲。

我的計時器是在Problem getting timer to work after cancelling one iteration and starting another,但爲了這個工作,當有人點擊一個按鈕它開始第一次倒計時,但時間排隊了,並顯示標題,然後當時間完成後將顯示其餘,然後在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"); 
} 

編輯:

我想我是不清楚我目前的計時器問題。由於消息正在排隊,它將變爲其餘,同時仍然減少剩餘的第一首歌曲的時間,因爲RunnableHandler正在處理的速度快得多。所以,這種方法存在缺陷,導致我認爲使用sendMessageDelayed這個設計不會像我所希望的那樣工作,但是,如果我只需要倒計時一次/按鈕點擊它將會很好,但我的需求要讓這一切都發生在點擊一個按鈕時,它會啓動該過程,然後在我的問題結束時模擬for循環。

+0

看看下面的想法。你可以很容易地查詢Listener構造函數中的歌曲列表,並創建一個ArrayList或任何你想要的,然後可以在if(!唱歌&& millis> = 20000L)塊中檢查它,以確定它是否應該調用一個新的'postDelayed()'或者只是返回; – Aleadam 2011-04-26 04:25:00

回答

1

在這裏,我們再次:)

我寫了這一點,並與Eclair的模擬器測試它在Eclipse中,並運行良好。一次點擊從54到0,然後從20到0,然後從45到0等,直到另一次點擊取消它。讓我知道它是否符合您的需求。當然UI只是最低限度:

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

非常感謝,再次。這幫助我超越了被卡住的地方。現在我需要看看我從你的例子中拿出了什麼,並理解爲什麼我沒有看到這樣的解決方案。 – 2011-04-27 02:20:17

+0

很高興幫助。經常發生在我身上的是思考問題的重點,我忽略了同樣的錯誤而忽略了這個問題,我需要一雙新的眼睛來幫助我發現錯誤。 – Aleadam 2011-04-27 03:01:29

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

我的解決方案與我的解決方案有同樣的問題,因爲下一個定時器的調度是問題所在。 – 2011-04-27 02:19:07