Autore Topic: eseguire lista di CountDownTimer non in parallelo  (Letto 550 volte)

Offline roberto.campione

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S4
  • Sistema operativo:
    Windows7
eseguire lista di CountDownTimer non in parallelo
« il: 29 Luglio 2013, 13:18:18 CEST »
0
Ciao a tutti! Questo è la mia prima discussione nel forum, quindi scusatemi se sbaglio qualcosa.
Mi sto appassionando alla programmazione android  e sto sviluppando la mia prima applicazione ma mi sono bloccato in un'activity in cui si dovrebbe iterare un  array di long e per ogni iterazione far partire un CountDownTimer settando il millisInFuture con l'elemento dell'array corrispondente; al termine del ciclo deve ripetere l'operazione con un nuovo CountDownTimer avente come millisInFuture il long dell'elemento dell'array.


Avevo pensato di salvare una lista di CountDownTimer e nel metodo onFinish di ogni oggetto far partire il CountDownTimer successivo. più o meno in questa maniera:

Codice: [Seleziona]
protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_gara);
                final TextView timer = (TextView) findViewById(R.id.countDownTextViewId);       
                final int[] tempiGara = getIntent().getExtras().getIntArray("com.roberto.rcrono.StartGara");
                                 
                        Log.i(TAG, "Numero di cicli da eseguire: " + tempiGara.length);
                        Log.i(TAG, "Tempo gara: " + tempiGara[0]);
               
                        final List <TimeCount> timeCounts = new LinkedList<TimeCount>();
                       
                        for (int i=0;i< tempiGara.length;i++ ){
                                final long tempoInMillis = tempiGara[i]*1000;
                               
                                TimeCount timeCount = new TimeCount(tempoInMillis,1000) {
                                       
                                        @Override
                                        public void onTick(long millisUntilFinished) {
                                                Log.i(TAG, "inTick di un Counter, tempoInMillis = " + tempoInMillis);
                                               
                                         timer.setText(String.valueOf(millisUntilFinished / 1000));
                                         
                                        }
                                       
                                        @Override
                                        public void onFinish() {
       
                                                Log.i(TAG, "Finish di un Counter");
                                               
                                                for(int  j = 0 ; j< timeCounts.size();j++){
                                                        Log.i(TAG, "Counter: " + timeCounts.get(j));
                                                       
                                                        if(j<(timeCounts.size()-1)){
                                                               
                                                                timeCounts.get(j+1).start();
                                                               
                                                        }
                                                        else {
                                                                 timer.setText("Done");
                                                                this.cancel();
                                                         }
                                                                                               
                                                }
                                       
                                                }
                                };
                                                                timeCounts.add(timeCount);
                                                               
                        }
                       
                        timeCounts.get(0).start();
               
        }
                       

Il problema è che i threads continuano a partire in parallelo e non riesco a gestire la cosa. Avevo pensato di utilizzare un AsyncTask e nel metodo postexecute far partire i CountDownTimer; Ma nonstante abbia letto un bel po' di documentazione non ho ben capito come usarlo e se effettivamente è la strada giusta da seguire.

Inoltre devo precisare che la classe TimeCount utilizzata nel mio codice è la stessa della CountDownTimer. Ho solo aggiunto il metodo setMillisInFuture

Codice: [Seleziona]
public void setMillisInFuture(long millisInFuture) {
    this.mMillisInFuture = millisInFuture;
}

che ho pensato che mi poteva servire. Ma niente, sono ancora riuscito a venirne a capo.

Voi cosa ne pensate? Come potrei risolvere questo problema?

Grazie mille in anticipo!!!

Roberto

Offline Giak

  • Utente junior
  • **
  • Post: 52
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    transformer tf101
  • Sistema operativo:
    ubuntu 12.10
Re:eseguire lista di CountDownTimer non in parallelo
« Risposta #1 il: 29 Luglio 2013, 13:59:52 CEST »
0
Non ho ben chiaro quello che vuoi fare, se riporti in modo dettagliato il tuo obiettivo potrei essere sicuramente più utile. innanzitutto mi pare che tu non abbia chiaro il concetto di activity e nemmeno quello di thread della UI.

Stai implementando del codice che fa molte new nel metodo onCreate, che per la cronaca viene chiamato ogni volta che l'activity viene creata o ad esempio quando ruoti il device da landscape a portrait.

Inoltre se i tempi sono i medesimi per tutti basta un unico timer, o un timer settato sul minimo comune multiplo tra i tempi.

Offline roberto.campione

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S4
  • Sistema operativo:
    Windows7
Re:eseguire lista di CountDownTimer non in parallelo
« Risposta #2 il: 29 Luglio 2013, 14:50:26 CEST »
0
Ciao e grazie per la risposta. Provo ad essere più chiaro:

Da un'activity precedente con una intent valorizzo un array di int
Codice: [Seleziona]
final int[] tempiGara = getIntent().getExtras().getIntArray("com.roberto.rcrono.StartGara");

questi valori possono essere tutti diversi tra di loro, ed ognuno rappresenterà la durata di un CountDownTimer (in secondi);

Io voglio che l'unica cosa che faccia questa activity è che quando viene lanciata, visualizzi su una TextView una serie di conti alla rovescia uno dopo l'altro, la cui durata di ognuno di questi sia pari (in secondi) al valore dell'elemento dell'array corrispondente.

Provo ad essere più chiaro con un esempio:

l'utente da un'activity precedente valorizza n editText inserendo dei tempi ( supponiamo che siano 3 editText impostati a 25, 15, 30), successivamente,  preme un pulsante che lancia l'activity in oggetto passandogli (con una intent) un array di interi con i tre elementi precedentemente valorizzati sugli editText
 
Codice: [Seleziona]
int[] tempiGara = {25, 15, 30}; 
ora voglio nella mia TextView compaia un primo conto alla rovescia di 25 secondi, appena termina questo, subito dopo un altro (nella stessa textView) di 15 secondi ed infine quello di 30 secondi. al termine di quest'ultimo comparirà un bottone che mi permetterà di avviare un'altra activity (questa parte del codice ancora non l'ho inserita).

Per questo motivo il mio codice l'ho inserito nella onCreate poichè voglio che i tempi alla rovescia partano istantaneamente al lancio dell'activity. inoltre non so a priori quanti saranno i conti alla rovescia da eseguire e che durata avranno poichè dipenderanno dall'input dell'utente.
Spero di essere stato più chiaro ora, almeno su quello che voglio ottenere :) grazie mille in anticipo!





Post unito: 29 Luglio 2013, 14:55:07 CEST
In metalinguaggio quello che voglio è:
Codice: [Seleziona]
List tempiGare [15000, 30000, 25000 ..... n ]
   for (long tempo : tempiGare) {
       
      ContoAllaRovescia[tempo] su una textView
       
                     
   }
// NB: nn voglio che i conti alla rovescia partano in parallelo, ma semplicemente uno al termine dell'altro
     //  i conti alla rovescia sono finiti

          textView ("Fine");
          Bottone vai avanti



« Ultima modifica: 29 Luglio 2013, 15:11:11 CEST da roberto.campione, Reason: Merged DoublePost »

Offline Giak

  • Utente junior
  • **
  • Post: 52
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    transformer tf101
  • Sistema operativo:
    ubuntu 12.10
Re:eseguire lista di CountDownTimer non in parallelo
« Risposta #3 il: 29 Luglio 2013, 18:48:14 CEST »
0
prendi un timer e un semplice intero come contatore, registri un tempo di tick di 1 secondo, ad ogni tick incrementi il contatore e quando arrivi al tempo prestabilito parti con il secondo contatore e cosi via.

il tutto può essere raffinato.

Offline roberto.campione

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S4
  • Sistema operativo:
    Windows7
Re:eseguire lista di CountDownTimer non in parallelo
« Risposta #4 il: 29 Luglio 2013, 21:35:58 CEST »
0
Cioè non dovrei usare dei CountdownTimer ma dei Timer() ?  Mi potresti fare un esempio di quello che dici?
In che senso può essere più raffinato?

Grazie mille

Offline Giak

  • Utente junior
  • **
  • Post: 52
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    transformer tf101
  • Sistema operativo:
    ubuntu 12.10
Re:eseguire lista di CountDownTimer non in parallelo
« Risposta #5 il: 30 Luglio 2013, 12:01:10 CEST »
0
puoi usare quello che ti pare, le due classi sono molto simili, sta poi a te raffinare l'implementazione a seconda delle tue necessità

sei usi un CountDownTimer lo inizializzi cosi:

CountDownTimer (<somma totale dei tempi>, <tempo di tick>)

il secondo è il tempo di tick, vedi te a che frequenza vuoi essere notificato, poi usi un contatore e tieni il conto di quanti tick ti mancano allo scadere di ciascun tempo.

dubito che se non sei in grado di comprendere il sistema di callback di un timer tu possa sviluppare un applicazione completa. io ti consiglio di studiare un buon libro, vedrai che dopo avrai una visione più chiara e impiegherai molto meno tempo in queste semplici implementazioni.
« Ultima modifica: 30 Luglio 2013, 12:03:24 CEST da Giak »

Offline roberto.campione

  • Nuovo arrivato
  • *
  • Post: 7
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S4
  • Sistema operativo:
    Windows7
Re:eseguire lista di CountDownTimer non in parallelo
« Risposta #6 il: 30 Luglio 2013, 14:53:39 CEST »
0
Giak ho risolto, evidentemente non sono stato molto chiaro con quello che intendevo. Comunque per tutti coloro che hanno capito quale era il mio obiettivo finale ecco il codice dell'activity:

Codice (Java): [Seleziona]
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_gara);
                final TextView timerTV = (TextView) findViewById(R.id.countDownTextViewId);
                final int[] tempiGara = getIntent().getExtras().getIntArray("com.roberto.rcrono.StartGara");

                Log.i(TAG, "Numero di cicli da eseguire: " + tempiGara.length);
                Log.i(TAG, "Tempo gara: " + tempiGara[0]);

                final List<CountDownTimer> timeCounts = new LinkedList<CountDownTimer>();


                for (int i = 0; i < tempiGara.length; i++) {
                        final long tempoInMillis = tempiGara[i] * 1000;

                        CountDownTimer timeCount = new CountDownTimer(tempoInMillis, 1000) {

                                @Override
                                public void onTick(long millisUntilFinished) {
                                        Log.i(TAG, "inTick di un Counter, tempoInMillis = " + tempoInMillis);
                                        Log.i(TAG, "millisec until finish / sec = " + (millisUntilFinished) + " / " + ((millisUntilFinished + 500) / 1000));
                                        //ho bisogno del +500 per visualizzare il primo numero

                                        timerTV.setText(String.valueOf((millisUntilFinished + 500) / 1000));

                                        // il motivo per cui non si vede l' "1" ovvero l'ultimo tick è questo
                                        // [url=http://stackoverflow.com/questions/12431180/android-countdowntimer-last-ontick-not-called-what-clean-solution-to-use]timer - android CountDownTimer - last onTick not called - what clean solution to use? - Stack Overflow[/url]
                                        // [url=http://stackoverflow.com/questions/8857590/android-countdowntimer-skips-last-ontick]java - Android: CountDownTimer skips last onTick()! - Stack Overflow[/url]
                                        // ed è cmq è facilmente risolvibile

                                                                                                                                                                                       
                                               
                                }

                                @Override
                                public void onFinish() {

                                        Log.i(TAG, "Finish di un Counter");

                                        int pos = timeCounts.indexOf(this);

                                        if (pos < timeCounts.size() - 1)
                                                timeCounts.get(pos + 1).start();

                                        else {
                                                timerTV.setText("Done");
                                                this.cancel();
                                        }

                                }

                        };
                        timeCounts.add(timeCount);

                }

                timeCounts.get(0).start();

        }