Autore Topic: Problema con gli eventi personalizzati  (Letto 1573 volte)

Offline Dani

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • danivitali
    • Mostra profilo
  • Dispositivo Android:
    Google Nexus One
Problema con gli eventi personalizzati
« il: 20 Luglio 2010, 19:48:20 CEST »
0
Ciao a tutti ragazzi!!
Ho un problema che riguarda più la programmazione Java anziché Android.
Sto imparando a programmare per Android e sto facendo un giochino solo che sono fermo a un punto.

Ho bisogno che quando la partita ha inizio, dopo 5 secondi venga modificata una TextView.
Ora, il fatto di accorgersi che sono passati 5 secondi l'ho risolto creando una sorta di timer che lancia un evento quando sono passati i secondi e questo funziona per certo

Il problema sta nel fatto che viene generata un'eccezione quando tenta di scrivere il testo nella TextView.

Spero di essere stato abbastanza chiaro.
Sotto ho riportato una parte del codice.

Grazie 1000 in anticipo!!!



Riporto il codice per realizzare il timer (ogni classe è in un file .java diverso) e la parte di codice nell'activity che genera l'eccezione.
N.B.: la creazione di eventi personalizzati è un argomento che ho imparato da solo qualche giorno fa. Il codice l'ho scritto io ma se ci sono critiche o conoscete un metodo migliore per far la stessa cosa vi prego di illuminarmi!! ;-) Thanks!!!

Codice (Java): [Seleziona]
//classe Timer
public class Timer implements Runnable {

        private int countdown; //millisecondi del timer
        private Thread th;
        private TimerListenersList listListeners;  //listener

        public Timer(int countdown) {
                this.countdown = countdown;
                th = null;
                listListeners = new TimerListenersList(this);
        }

        public void run() {
                try {    //non fa altro che attendere
                                th.sleep(countdown);
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                        listListeners.EndTimeEvent();  //lancia l'evento
                }
       

        public void start() {  //inizializza e fa partire il thread
                if (th == null) {
                        th = new Thread(this);
                        th.start();
                }
        }

        public void addTimerListener(onTimerListener tl) {
                listListeners.addTimerListener(tl);
        }

        public void removeTimerListener(onTimerListener tl) {
                listListeners.removeTimerListener(tl);
        }

}

//Classe TimerListenersList
import java.util.ArrayList;

public class TimerListenersList {
        private Object sorgente;
        private ArrayList<Object> listeners;

        public TimerListenersList(Object sorgente) {
                this.sorgente = sorgente;
                listeners = new ArrayList<Object>();
        }

        public void addTimerListener(onTimerListener tl) {
                listeners.add(tl);
        }

        public void removeTimerListener(onTimerListener tl) {
                listeners.remove(tl);
        }

        public void EndTimeEvent() {
                TimerEvent event = new TimerEvent(sorgente);
                ArrayList<Object> copy_listeners = listeners;
                for (int i = 0; i < copy_listeners.size(); i++) {
                        ((onTimerListener) copy_listeners.get(i)).onClock(event);
                }
        }
}



//Classe TimerEvent
import java.util.EventObject;

public class TimerEvent extends EventObject{

        public TimerEvent(Object source) {
                super(source);
        }
}

//Interfaccia onTimerListener

public interface onTimerListener {
        public void onClock(TimerEvent te);
}



Qui invece è riportato parte del codice dell'activity del gioco:
Codice (Java): [Seleziona]
private void BeginMatch() {
        t = new Timer(5000); // setup timer. La sua dichiarazione è già stata fatta come variabile globale dell'activity
        t.addTimerListener(new onTimerListener() {
                       
              @Override
               public void onClock(TimerEvent te) {
                        txtScore.setText("FUNZIONA");   //modifico la TextView già associata alla view in precedenza
                               
                }
        });
        t.start(); // start match
}

Offline blackgin

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1387
  • Respect: +164
    • Google+
    • blackgins
    • blackginsoft
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Nexus
  • Sistema operativo:
    Mac OSX 10.8
Re:Problema con gli eventi personalizzati
« Risposta #1 il: 20 Luglio 2010, 20:52:01 CEST »
0
Il txtScore dove lo definisci? (Ho capito che l'hai inizializzato, ma materialmente dov'é?)
Postate il LogCat LogCat LogCat LogCat LogCat

Offline Qlimax

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 757
  • Respect: +202
    • Google+
    • _Qlimax
    • Mostra profilo
    • www.egsolutions.ch
  • Dispositivo Android:
    Galaxy Nexus - Nexus One - Wildfire - Magic
  • Play Store ID:
    egsolutions.ch
  • Sistema operativo:
    Ubuntu 12.04, Windows 7
Re:Problema con gli eventi personalizzati
« Risposta #2 il: 20 Luglio 2010, 22:10:30 CEST »
+1
Io userei la classe java.util.Timer e TimerTask, invece di crearmi un evento personalizzato.

inoltre per modificare la UI da una thread (TimerTask lo è) , in android hai bisogno di un handler.

ecco un esempio che fa quello che vuoi tu:
Codice (Java): [Seleziona]
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Handler.Callback;
import android.widget.TextView;

public class Demo extends Activity {
        TextView tv;
        Handler tvHandler;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tv=(TextView)findViewById(R.id.tv);
       
       

        tvHandler=new Handler(new Callback() {
                       
                        @Override
                        public boolean handleMessage(Message msg) {
                                tv.setText("Hello Timer !");
                                return true;
                        }
                });
       

        beginMatch();
       
    }
   
    private void beginMatch(){
        Timer t=new Timer();
        TimerTask task=new TimerTask(){

                        @Override
                        public void run() {
                               
                                tvHandler.sendEmptyMessage(0);
                        }
               
        };
       
       
        t.schedule(task, 5000);
    }
}

;)


Offline ScarfaceIII

  • Utente junior
  • **
  • Post: 112
  • Respect: +13
    • raferalston12
    • Mostra profilo
  • Dispositivo Android:
    Nexus One
  • Sistema operativo:
    GNU/Linux, Ubuntu 10.04 / Windows 7
Re:Problema con gli eventi personalizzati
« Risposta #3 il: 20 Luglio 2010, 22:45:31 CEST »
0
Io userei la classe java.util.Timer e TimerTask, invece di crearmi un evento personalizzato.

inoltre per modificare la UI da una thread (TimerTask lo è) , in android hai bisogno di un handler.

non voglio fare il saputello dell'ultim'ora, ma volevo dire la stessa cosa: usare Timer e TimerTask, solo che sono stato scoraggiato dal codice postato, mi son detto: "ma se ha fatto tutto quel popo' di roba, magari ci aveva pensato già al TimerTask e non gli basta..." (sarà che sto letteralmente fondendo il cervello dietro ad un altro progetto e mi rimane poco da dare agli altri...)
Per l'handler: non ci avevo pensato, ma daltronde, come non quotare "l'Illuminato" Qlimax?!

Offline Dani

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • danivitali
    • Mostra profilo
  • Dispositivo Android:
    Google Nexus One
Re:Problema con gli eventi personalizzati
« Risposta #4 il: 21 Luglio 2010, 09:36:26 CEST »
0
Citazione
Il txtScore dove lo definisci?
Lo definisco come variabile globale e poi lo assegno al rispettivo widget nella chiamata onCreate.

Per Qlimax e ScarfaceIII:
avevo pensato al Timer che mi mette a disposizione java, ma non ricordo perchè avevo scartato l'idea. La gestione del tempo in java è anche quello un tema nuovo per me... scusatemi l'ignoranza :-P
Comunque il tuo codice Qlimax è perfetto per quello che mi serve!!! Grazie 1000!

Ma una domanda ancora se posso: che cosa è un handler e quale è la sua funzione?

Offline MarcoDuff

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1073
  • Respect: +202
    • Google+
    • marcoduff
    • Mostra profilo
    • MarcoDuff's Blog
  • Dispositivo Android:
    Samsung Galaxy Nexus
  • Play Store ID:
    MarcoDuff
  • Sistema operativo:
    Windows 7
Re:Problema con gli eventi personalizzati
« Risposta #5 il: 21 Luglio 2010, 09:44:07 CEST »
+1
Mi associo completamente alla soluzione di Qlimax, anche perchè su android è l'unica strada percorribile!  o_O

Mi spiego meglio: per accedere alle risorse dell'interfaccia grafica di android (comunemente le View e le sue derivate) bisogna obbligatoriamente stare nel Thread principale dell'Activity. Se ti sposti di Thread non puoi accedere alle modifiche (ecco il motivo della tua eccezione iniziale).

Se sei in una altro Thread, l'unico modo che hai per tornare nel Thread dell'Activity è usare un Handler, ecco perché l'unica strada percorribile è quella di Qlimax. Avendo l'Handler la possibilità di posticipare la sua partenza (grazie ai metodi postDelayed, postAtTime, sendEmptyMessageAtTime, sendEmptyMessageDelayed, e altri...) riesci a scrivere con poche righe di codice un Timer, senza utilizzare Timer, TimerTask o Thread in modo diretto (fa tutto Android per te!!!):

Codice (Java): [Seleziona]
public class AndroidTestActivity extends Activity {
        @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                                TextView textView = (TextView)findViewById(R.id.hello);
                                textView.setText("Passati 5000 ms");
                        }
                }, 5000);
    }
}

Ciao!

Offline Dani

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • danivitali
    • Mostra profilo
  • Dispositivo Android:
    Google Nexus One
Re:Problema con gli eventi personalizzati
« Risposta #6 il: 21 Luglio 2010, 11:24:09 CEST »
0
Ok marcoDuff, chiaro.
Però se tu dovessi dare una definizione di handler che diresti?
Per quel che ho capito dai vostri esempi direi che è una sorta di thread/non thread però non mi è chiaro il concetto.

Conoscete un tutorial o una guida che tratti di questo argomento? Ho cercato con google ma niente...

Ho fatto 5 anni di programmazione a scuola e non ne ho mai sentito parlare uff! :'( (almeno non esplicitamente).

Offline MarcoDuff

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1073
  • Respect: +202
    • Google+
    • marcoduff
    • Mostra profilo
    • MarcoDuff's Blog
  • Dispositivo Android:
    Samsung Galaxy Nexus
  • Play Store ID:
    MarcoDuff
  • Sistema operativo:
    Windows 7
Re:Problema con gli eventi personalizzati
« Risposta #7 il: 21 Luglio 2010, 11:54:43 CEST »
+1
Diciamo che la definizione più semplice che trovo è "un modo per far comunicare due Thread diversi". Non è rigorosa, e non è precisa, in ambito android va più che bene.

In particolare, su android, viene utilizzato per evitare il problema ANR - Application Not Responding, ovvero nello spostare processi lunghi (lettura scrittura su sd, connessioni di rete, ecc...) dal thread principale (quello che si occupa delle View e quindi delle interazioni con l'utente) ad un thread secondario (maggiori info).

Offline Qlimax

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 757
  • Respect: +202
    • Google+
    • _Qlimax
    • Mostra profilo
    • www.egsolutions.ch
  • Dispositivo Android:
    Galaxy Nexus - Nexus One - Wildfire - Magic
  • Play Store ID:
    egsolutions.ch
  • Sistema operativo:
    Ubuntu 12.04, Windows 7
Re:Problema con gli eventi personalizzati
« Risposta #8 il: 21 Luglio 2010, 11:57:42 CEST »
+1
@Marco giusto, postDelayed fa già tutto lui :)
ad ogni modo Timer e TimerTask, sono classi utili da conoscere , non credo possano essere completamente sostituite dai metodi della classe Handler

@Dani
la classe Handler in questione, appartiene esclusivamente ad android. forse è per questo che non ne hai mai sentito parlare. (ed anche per questo è utile conoscere Timer e TimerTask)
la definizione di Handler la trovi qui:
Handler | Android Developers




Offline Dani

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • danivitali
    • Mostra profilo
  • Dispositivo Android:
    Google Nexus One
Re:Problema con gli eventi personalizzati
« Risposta #9 il: 21 Luglio 2010, 13:51:09 CEST »
0
Chiaro!!!
Grazie 1000 ad entrambi MarcoDuff e Qlimax!! :-)