2012-11-20 16 views
5

मैं एंड्रॉइड 2.2 के लिए क्रोनोमीटर/उलटी गिनती टाइमर ऐप डिज़ाइन करने की प्रक्रिया में हूं और एक बटन को क्रोनोमीटर और दोनों टाइमर को शुरू करने के लिए प्रेस करना चाहता हूं। तो, आदर्श रूप में, मुझे पर सेकंड्स (समय) पर एक ही उदाहरण में बदलने के लिए क्रोनोमीटर और टाइमर दोनों चाहिए। (क्रोनोमीटर गिनती होने के बावजूद टाइमर गिना जाएगा)। जब से मैं एंड्रॉयड द्वारा प्रदान की ठीक घड़ी और टाइमर कार्यक्षमता का उपयोग कर रहा है, मैं कोड का निम्न भाग लिखा है जब उपयोगकर्ता 'प्रारंभ करें' बटनएंड्रॉइड में एक साथ दो (या अधिक) फ़ंक्शंस शुरू करना

private boolean mStartPressedOnce = false; 
long mTimeWhenStopped = 0; 
Chronometer mChronometer; 
MyCounter mCounter; 
... 
@Override 
public void onClick(View v) { 
    switch (v.getId()) { 
    case R.id.StartButton: 
     // Perform some initialization for the chronometer depending 
     // on the button press 
     if (mStartPressedOnce == false) { 
      mChronometer.setBase(SystemClock.elapsedRealtime()); 
     } else { 
      mChronometer.setBase(SystemClock.elapsedRealtime() + mTimeWhenStopped); 
     } 

     // Perform the initialization for the timer 
     mCounter = new MyCount(45000, 1000); 

     // Fire up the chronometer 
     mChronometer.start(); 

     // Fire up the timer 
     mCounter.start(); 
     break; 

     case R.id.ResetButton: 
      // Reset the chronometer 
      mChronometer.setBase(SystemClock.elapsedRealtime()); 
      mTimeWhenStopped = 0; 
      break; 

     case case R.id.StopButton: 
      mStartPressedOnce = true; 
      // Stop the chronometer 
      mTimeWhenStopped = mChronometer.getBase() - SystemClock.elapsedRealtime(); 
      mChronometer.stop(); 
      break; 
    } 

... 

public class MyCounter extends CountDownTimer { 

    @Override 
    public MyCount(long millisInFuture, long countDownInterval) { 
     super(millisInFuture, countDownInterval); 
    } 

    @Override 
    public void onFinish() {   
     // Nothing to do here 
    } 

    @Override 
    public void onTick(long millisUntilFinished) { 
     long seconds = (long) (millisUntilFinished/1000); 
     long minutes = (long) ((millisUntilFinished/1000)/60); 
     long hours = (long) (((millisUntilFinished/1000)/60)/60); 

     // Do some formatting to make seconds, minutes and hours look pretty  

     // Update the timer TextView    
     (TextView) findViewById(R.id.CountDownTimerTextView)) 
      .setText(hours + ":" + minutes + ":" + seconds); 
    } 
} 

प्रेस हालांकि यह ठीक घड़ी और टाइमर पर सेकंड की तरह दिखता है में हैं सिंक प्रारंभ में, थोड़े समय के बाद, वे बंद हो जाते हैं और दोनों के लिए दूसरे अपडेट अलग-अलग होते हैं।

सोच रहा था कि मैं इसे ठीक करने के लिए क्या कर सकता था। मैं भर में आया था - और इस थ्रेड

Running multiple AsyncTasks at the same time -- not possible?

मुझे लगता है हो सकता है एक डिजाइन बदलाव की जरूरत पढ़ा लेकिन मुझे यकीन है कि वास्तव में क्या किया जाना चाहिए नहीं कर रहा हूँ।

संपादित करें: समय की गणना घड़ी का उपयोग कर के लिए ठीक घड़ी और टाइमर और विधि के लिए शामिल प्रकार - jolivier और njzk2 के सुझावों के अनुसार

+2

आपके एम क्रोनोमीटर और एमकॉन्टर क्या हैं और आप समय को कैसे मापते हैं? – njzk2

+0

आप System.nanoTime() या currentTimeMillis() के बजाय विजेट का उपयोग क्यों कर रहे हैं? – Shark

+0

@ शार्क, सुनिश्चित नहीं है कि मुझे आपके प्रश्न का उत्तर पता है। धन्यवाद। – aLearner

उत्तर

1

तो, कुछ समय के लिए इसे खत्म करने के बाद और सुझाव jolivier से बाहर जाने के बाद, इसलिए हमारे साथ उदारता से साझा किया गया, मुझे एहसास हुआ कि onChronometerTick नामक एक विधि मौजूद है जिसे हर बार क्रोनोमीटर टिक (हर सेकेंड) कहा जाता है मामला)। इसलिए, मैंने प्रत्येक बार विधि कहने पर काउंटर से 1000 मिलीसेकंड घटाकर सोचा और टाइमर डिस्प्ले को अपडेट किया। मैं एंड्रॉइड टाइमर टुकड़ा (CountDownTimer) से पूरी तरह से छुटकारा पा लिया। मैंने सोचा कि यह एक ही समय में दोनों डिस्प्ले अपडेट करने का एक अच्छा तरीका होगा। यह एक टाइमर का एक सरल कार्यान्वयन भी है।

मुझे यह रिपोर्ट करने में प्रसन्नता हो रही है कि यह अच्छी तरह से काम करता है। टाइमर और क्रोनोमीटर दोनों वास्तव में एक ही समय में अपडेट होते हैं। तो, मूल प्रश्न ऐसा लगता है कि इसका उत्तर दिया गया है। दुर्भाग्य से, मैं टाइमर फ्रंट पर एक ऑफ-टू-दो त्रुटि में भाग गया जिसे मैंने बदसूरत हैक के साथ तय किया। मैं अब तक जो पोस्ट कर रहा हूं उसे पोस्ट कर रहा हूं। हैक को ठीक करने या कोड में सुधार करने के बारे में कोई सुझाव स्वागत है। ध्यान दें कि मैंने कोड को टिप्पणी करने के लिए टिप्पणी की है कि यह समझने में आसान हो कि क्या किया गया है।

बग के लिए संपादित करें: एक और बात मैंने देखा है कि लगभग 10 मिनट या तो क्रोनोमीटर और टाइमर एक सेकंड से बंद होते हैं।अधिक सटीक, टाइमर एक सेकंड से क्रोनोमीटर के पीछे है। अभी तक यह सुनिश्चित नहीं है कि ऐसा क्यों होता है।

private boolean mStartPressedOnce = false; 
long mTimeWhenStopped = 0; 
Chronometer mChronometer; 
long millisUntilFinished = 0; 
boolean firstPassOver = false; 
int counter = 0; 
... 
@Override 
public void onClick(View v) { 
    switch (v.getId()) { 
    case R.id.StartButton: 
     // Perform some initialization for the chronometer depending 
     // on the button press 
     if (mStartPressedOnce == false) { 
      mChronometer.setBase(SystemClock.elapsedRealtime()); 
     } else { 
      mChronometer.setBase(SystemClock.elapsedRealtime() + mTimeWhenStopped); 
     } 

     // Fire up the chronometer 
     mChronometer.start(); 
     break; 

     case R.id.ResetButton: 
      // Reset the chronometer 
      mChronometer.setBase(SystemClock.elapsedRealtime()); 
      mTimeWhenStopped = 0; 
      break; 

     case case R.id.StopButton: 
      mStartPressedOnce = true; 
      // Stop the chronometer 
      mTimeWhenStopped = mChronometer.getBase() - SystemClock.elapsedRealtime(); 
      mChronometer.stop(); 
      break; 
    } 

... 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.stop_watch); 

    mChronometer = (Chronometer) findViewById(R.id.StopWatchTextView); 

    // Initialize the number of milliseconds before the timer expires (
    // set the timer) - in this case to 46 seconds 
    millisUntilFinished = 46000; 

    // Display how many seconds remain before the timer expires 
    ((TextView) findViewById(R.id.CountDownTimerTextView)).setText(hours 
      + ":" + minutes + ":" + millisUntilFinished/1000); 

    // In line with the suggestion provided by jolivier - make the timer 
    // the slave and update its display every time the chronometer 
    // ticks   
    mChronometer 
      .setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() { 

       @Override 
       public void onChronometerTick(Chronometer chronometer) { 

        // Update the display for the chronometer 
        CharSequence text = chronometer.getText();     
        chronometer.setText(text); 

        // Update the display for the timer     
        // !!! BUG !!! 
        // Looks like onChronometerTick is called at the 0th second 
        // and this causes an off by two error if a count down timer 
        // is being implemented. Fixed it with this hack. There's gotta 
        // be a more elegant solution, though. 
        if(counter >= 2) { 
         millisUntilFinished1 = millisUntilFinished1 - 1000; 
         counter = 2; 
        } 
        counter++; 

        if (millisUntilFinished >= 0) { 

         long seconds = (long) (millisUntilFinished/1000); 
         long minutes = (long) ((millisUntilFinished/1000)/60); 
         long hours = (long) (((millisUntilFinished/1000)/60)/60); 

         // Do some formatting to make seconds, minutes and hours look pretty  

         // Update the timer TextView  
         ((TextView) findViewById(R.id.CountDownTimerTextView)) 
           .setText(hours + ":" + minutes + ":" 
             + seconds); 
         } 
        } 

    }); 
    // Other code 
    ... 
} 
+1

वास्तव में घड़ी के लिए केवल एक धागे का उपयोग करके मेरा मतलब था और हर समय तर्क इस पर निर्भर करता है। आपका हैक इस तथ्य से आ सकता है कि जब आप क्रोनोमीटर पर 'प्रारंभ() '' कॉल करते हैं तो 'क्रोनोमीटर लिस्टर' को बुलाया जाता है। इस श्रोता के बारे में दस्तावेज काफी अधूरा है और आपका कोड हर सेकेंड कहलाता है लेकिन इसे अधिक बार कहा जा सकता है, जब आप इसे वास्तव में बुलाया जाता है तो आप इस कोड के बाहर परीक्षण करना चाहेंगे। – jolivier

+0

वाह! धन्यवाद। मैं आपके सुझाव के लिए आभारी हूं और खुश हूं कि कार्यान्वयन आपके लिए जितना कम या कम है। आप 'ऑनक्रोनोमीटर टिक' के बारे में सही हैं - ऐसा लगता है कि इसे दो बार कहा जाता है - लेकिन केवल तभी जब 'mChronometer.start()' कहा जाता है। इसके बाद ऐसा लगता है कि हर सेकेंड में सिर्फ एक बार कहा जाता है। अजीब। मुझे आश्चर्य है कि इस समस्या का एक सुंदर फिक्स क्या है। – aLearner

+0

मैंने यहां सामने आए दो बगों पर ध्यान केंद्रित करने के लिए एक नया धागा शुरू किया। ऐसा लगता है कि 'ऑन क्रोनोमीटर टिक' को दोषी ठहराया जा सकता है। अधिक जानकारी के लिए, कृपया http://stackoverflow.com/questions/13523804/onchronometertick-called-two- समय- पहले-chronometer-value-changes देखें – aLearner

2

आप System.currentTimeMillis() के साथ वर्तमान समय पुनः प्राप्त यह एक चर में स्टोर कर सकते हैं और इसे mChronometer और mCounter दोनों पर अग्रेषित करें, ताकि वे एक ही समय संदर्भ का उपयोग कर सकें, हालांकि उनका कार्य अलग-अलग समय पर शुरू हुआ।

संपादित करें: दिए गए प्रकारों के साथ, android documentation about Chronometer आपको बताएगा कि आप जो कहा है उसे प्राप्त करने के लिए आप elapsedRealTime का उपयोग कर सकते हैं। CountDownTimer में यह नहीं है और इसकी start विधि अंतिम है इसलिए आप अन्य कार्यान्वयन का उपयोग करना चाह सकते हैं, आपके उपयोग के मामले का एक बेहतर दृश्य हमारी मदद कर सकता है।

मूल रूप से, एक ही मिलीसेकंड में एक क्रिया करने के लिए दो धागे चाहते हैं, यह कभी भी एक अच्छा विचार नहीं है, उनमें से एक घड़ी के रूप में काम करेगा और दूसरा एक गुलाम होना चाहिए और घड़ी को सुनना चाहिए।

+0

आपके उत्तर के लिए धन्यवाद। मुझे यकीन नहीं है कि जब आप कहते हैं कि वैरिएबल में संग्रहीत मूल्य को 'mChronometer' और' mCounter' 'पर अग्रेषित करने की आवश्यकता है, तो मेरा क्या मतलब है। मैंने 'mChronometer.start()' और 'mCounter.start()' विधियों को देखा लेकिन ऐसा लगता है कि वे प्रारंभिक मान स्वीकार नहीं करते हैं (जो 'System.currentTimeMillis()' का उपयोग करके प्राप्त किया गया था और संग्रहीत किया गया था क्या आप वहां मौजूद हैं)। तो, दूसरे शब्दों में, 'mChronometer.start (प्रारंभिक वैल)' या 'mCounter.start (प्रारंभिक वैल) 'जैसी कुछ भी नहीं है। या मैंने बस आपके सुझाव को गलत समझा? – aLearner

+0

क्या आप अपने प्रश्न में mChronometer और mCounter का प्रकार दे सकते हैं? मुझे आपकी मदद करने के लिए इसकी आवश्यकता होगी – jolivier

+0

@ njzk2 चीजों को स्पष्ट करने के लिए बस कुछ और कोड जोड़ा गया। धन्यवाद। – aLearner

संबंधित मुद्दे