Autore Topic: GridView e refresh della View  (Letto 966 volte)

Offline giulius89

  • Nuovo arrivato
  • *
  • Post: 4
  • Respect: +1
    • Mostra profilo
  • Dispositivo Android:
    LG Optimus Dual - P990
  • Sistema operativo:
    Windows 7 32bit
GridView e refresh della View
« il: 27 Giugno 2011, 19:56:04 CEST »
0
Salve a tutti,
mi è stato difficile capire in quale sezione postare il problema che sto per sottoporvi, poiché è al confine di molte sezioni. Innanzitutto, per introdurre un po' la questione, parto con il dire che sto sviluppando una normalissima applicazione con API level 8 (più che sufficienti per le mie esigenze) con ambiente di sviluppo Eclipse Helios sotto Windows 7 32bit. Premetto, inoltre, che mi sono avvicinato da poco alla programmazione su android e che, quindi, alcuni automatismi non mi sono ancora molto chiari (perciò mi scuso anticipatamente per eventuali future affermazioni o domande stupide).

Per motivi didattici devo sviluppare sotto android il gioco in cui si devono mettere 4 pedine in fila per vincere (non voglio usare nomi commerciali :-P); pertanto, la mia view di gioco (escludendo i menù, ovviamente) non è altro che una matrice 6x7 di pedine, che possono essere vuote, piene per il giocatore 1 o piene per il giocatore 2. Ho sviluppato, a tal fine, anche una piccola intelligenza artificiale, così da poter giocare contro il computer. La grafica è realizzata mediante una GridView che riempio con immagini png, cui ho annesso un ImageAdapter (specializzazione di BaseAdapter trovata su internet) che ha come data source un array contenente le 42 pedine, con i giusti colori. Ho associato anche un OnClickListener sugli elementi, cosicché al click so dove l'utente voglia fare la mossa. Il problema è che, dopo una mossa dell'utente, sebbene io aggiorni l'array di pedine subito dopo aver effettuato la mossa (prima dell'utente, poi del computer), sullo schermo non appare assolutamente nulla; devo aspettare per forza la terminazione del metodo OnClick, affinché si apprezzi il cambiamento sullo schermo. Ho provato di tutto (dopo giorni di ricerche estenuanti su google): dapprima ho provato ad invocare la notifyDataSetChanged() dopo ogni inserimento, ma il refresh avveniva sempre dopo; poi ho provato a farlo anche in un thread separato, ma crasha  (forse non son stato capace di farlo); poi ho provato a forzare un invalidate() della View, ma niente neanche con quello!! Insomma, non so più cosa fare!!!!!!!!!! Tutto questo, tra l'altro, mi inibisce anche dalla possibilità di fare una "pseudo-animazione" per rendere il programma più "appealing" ;-)

Scusate la lunghezza del post, ma ho proprio bisogno!!!! Se c'è qualcosa di poco chiaro, dite pure!!

Grazie a tutti

Offline 7h38ugg3r

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1200
  • Respect: +133
    • riccardofischetti
    • th38ugg3r
    • @7h38ugg3r
    • Mostra profilo
  • Dispositivo Android:
    Galaxy-S GT I-9000/ ASUS Eee Pad Transformer
  • Play Store ID:
    Riccardo Fischetti
  • Sistema operativo:
    OS X Lion / Linux Mint 11 (Katya)
Re:GridView e refresh della View
« Risposta #1 il: 28 Giugno 2011, 14:24:32 CEST »
0
perché non cominci a postare un po' di codice?
magari proprio dell'onclick.

7h38ugg3r<=>thebugger
Non conosci Java? Allora sei nel posto sbagliato!

http://www.androidpatterns.com/

Offline giulius89

  • Nuovo arrivato
  • *
  • Post: 4
  • Respect: +1
    • Mostra profilo
  • Dispositivo Android:
    LG Optimus Dual - P990
  • Sistema operativo:
    Windows 7 32bit
Re:GridView e refresh della View
« Risposta #2 il: 28 Giugno 2011, 14:56:32 CEST »
0
Ecco il codice della onClick:

Codice (Java): [Seleziona]
public void onItemClick(AdapterView<?> parent,View v,int position,long id)
{
        int colonnaDaRiempire = position % colonne;
       
        //verifico se la colonna è piena
        if (! partita.piena(matrice, colonnaDaRiempire))
        {
                int rigaVuota = partita.trovaRiga(matrice, colonnaDaRiempire);
                matrice = partita.mettiPedina(matrice, colonnaDaRiempire, giocatore);
                immaginiMenu.mettiPedina(colonne * rigaVuota + colonnaDaRiempire, giocatore);
               
                giocatore = (giocatore % 2) + 1;
               
                if (partita.controllaVittoria(matrice) != 0)
                {
                        //gestisci fine partita
                }
                else
                {
                        //se gioco contro il computer, devo innescare l'IA
                        if (modalita.equals("singolo"))
                        {
                            elaborazione.setVisibility(View.VISIBLE);
                            colonnaDaRiempire = partita.mossaComputer(matrice, giocatore);
                            rigaVuota = partita.trovaRiga(matrice, colonnaDaRiempire);
                            matrice = partita.mettiPedina(matrice, colonnaDaRiempire, giocatore);
                                                       
                            immaginiMenu.mettiPedina(colonne * rigaVuota + colonnaDaRiempire, giocatore);

                            giocatore = (giocatore % 2) + 1;

                            if (partita.controllaVittoria(matrice) != -1)
                            {
                                //gestisci fine partita
                            }
                        }
               }
                if(! modalita.equals("multi-online")) salvaStato(c);
}

al di là delle varie strutture dati che mi sono creato per modificare la matrice (ossia partita ecc), una volta modificatala eseguo l'istruzione:

Codice (Java): [Seleziona]
immaginiMenu.mettiPedina(colonne * rigaVuota + colonnaDaRiempire, giocatore);
immaginiMenu è un'istanza dell'image adapter di cui non riporto tutto il codice, ma di cui riporto il codice di mettiPedina:

Codice (Java): [Seleziona]
       
        if(giocatore == 1)
                pulsanti[position] = R.drawable.classic_player1;
        else if (giocatore == 2)
                pulsanti[position] = R.drawable.classic_player2;
        else
                pulsanti[position] = R.drawable.classic_player_vuoto;
        this.notifyDataSetChanged();

Così facendo vado a modificare il dataSet. Il problema è che nonostante il notifyDataSetChanged(), il refresh della view avviene solo al termine della onClick, mentre vorrei avvenisse "in tempo reale".
« Ultima modifica: 28 Giugno 2011, 14:58:29 CEST da giulius89, Reason: Ho inviato per errore, senza terminare il post, scusate. »

Offline EmilioCuomo

  • Nuovo arrivato
  • *
  • Post: 29
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy Tab 10.1v
  • Sistema operativo:
    Windows
Re:GridView e refresh della View
« Risposta #3 il: 29 Agosto 2011, 14:13:43 CEST »
0
Mi premerebbe sapere se hai risolto
Ho lo stesso problema con un simplecursoradapter di cui non riesco a fare il requery

Offline giulius89

  • Nuovo arrivato
  • *
  • Post: 4
  • Respect: +1
    • Mostra profilo
  • Dispositivo Android:
    LG Optimus Dual - P990
  • Sistema operativo:
    Windows 7 32bit
Re:GridView e refresh della View
« Risposta #4 il: 29 Agosto 2011, 14:32:51 CEST »
+1
Sì, ho risolto da poco e, forse, in maniera non perfetta, ma ce l'ho fatta!!! Il concetto è molto semplice e, probabilmente, anche banale, ma ne ho compreso il senso solo ora: TUTTE le modifiche alla UI vengono effettuate dal thread principale dell'applicazione, che è anche quello su cui girano i callback come l'OnClickListener di cui sopra. Ne consegue che, fino alla terminazione di tutte le istruzioni all'interno della OnClick, la UI non può essere aggiornata. Qual è allora la soluzione? Basta spostare tutto il blocco di istruzioni da far eseguire all'atto del click all'interno di un Runnable da far girare in un nuovo thread; dentro la OnItemClick dovrà essere presente solo l'istruzione di risveglio di questo thread secondario. In tale modo la OnItemClick "si sbrigherà" a terminare, liberando il thread principale, pronto ad effettuare modifiche. L'unica condizione è che, se si vuole effettuare qualche modifica grafica dal thread secondario, essa sia racchiusa all'interno di un blocco di questo tipo:

Codice (Java): [Seleziona]
//avviso l'utente che il computer
//sta elaborando la mossa
runOnUiThread(new Runnable()
{
        public void run()
        {
                elaborazione.setVisibility(View.VISIBLE);
        }
});

In questo caso quello che faccio è settare a visibile la TextView "elaborazione". Siccome lo sto facendo da un thread secondario, non posso invocare direttamente la setVisibility, altrimenti verrebbe lanciata un'eccezione; è sufficiente, però, racchiuderlo nel metodo run di un nuovo Runnable (creato al volo) da far girare sul thread UI.

Spero di essere stato chiaro  :-)

P.S. devo mettere topic risolto? Scusate la domanda idiota  :-P