JavascriptProva

giovedì 22 settembre 2016

Cercare un elemento in un recordset, e ripasso di ArrayAdapter e CustomAdapter.

Che dobbiamo fare con quel database?

Dobbiamo archiviare le parole comprese dal sistema in un database, e a ogni parola pronunciata la parola compresa va confrontata con quelle presenti: se assenta va aggiunta.
Proviamo quindi inventandoci le parole...

Saggiare la lunghezza di un recordset avente come clausola WHERE la ricerca della parola.
Per fare questo devo creare un metodo del database di tipo query() avente per parametro la parola stessa, quindi se la lunghezza del recordset è pari a zero questo significa che non c'è, se è pari a 1, vuol dire che c'è.
Ho in mente il nucleo del progetto.
Ci provo...

    public Cursor query(String string){
        SQLiteDatabase db=this.getWritableDatabase();
        Cursor crs=db.rawQuery("SELECT * FROM TABELLA WHERE TEXT ="+string, null);
        return crs;
    }
Questo è il metodo.
Ora provo ad applicarlo. Prima però mi ricostruisco il "visore" del database, per il quale mi serve anche il metodo query senza parametri:
    public Cursor query(){
        SQLiteDatabase db=this.getWritableDatabase();
        Cursor crs=db.rawQuery("SELECT * FROM TABELLA", null);
        return crs;
    }
Ora li applichiamo...

Siamo giunti all'applicazione finale. Ecco...

        Cursor crsSelect=helper.query("fanculo");
        int numero=crsSelect.getCount();
        System.out.println(numero);
        if(numero==0) helper.save("fanculo");7
Questo codice (esclusa la terza riga) mi cerca un record in una tabella, e se non ce lo trova lo aggiunge.
Credo che si possa anche sintetizzare in un solo comando. Ci provo:
    public void addIfNotPresent(String string){
        Cursor crsSelect=helper.query(string);
        if(crsSelect.getCount()==0) helper.save(string);
    }
E la provo così:
addIfNotPresent("ciccia");
Vediamo...

Ottimo! L'ho sperimentato: aggiunge una voce se non è contenuta nella tabella.
Ma mi piacerebbe adesso fare una rilevazione statistica della frequenza con cui una voce, se presente, figura, e aumentare il numero.

A tale scopo rimetto le mani sul database.

    public Helper(Context context) {
        super(context, "mioDatabase.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE TABELLA(_ID INTEGER PRIMARY KEY, TESTO TEXT, NUMERO INTEGER)");
    }

    public Cursor query(String string){
        SQLiteDatabase db=this.getWritableDatabase();
        Cursor crs=db.rawQuery("SELECT * FROM TABELLA WHERE TESTO = '"+string+"'", null);
        return crs;
    }

    public Cursor query(){
        SQLiteDatabase db=this.getWritableDatabase();
        Cursor crs=db.rawQuery("SELECT * FROM TABELLA", null);
        return crs;
    }

    public void save(String parola){
        SQLiteDatabase db=this.getWritableDatabase();
        ContentValues values=new ContentValues();
        values.put("TESTO",parola);
        values.put("NUMERO",0);
        db.insert("TABELLA",null,values);
Ma ora devo visualizzare su una GridView, non più su una ListView.
Cosa cambia?

Cambia che la visualizzazione su GridView non mi sembra adeguata in quanto con l'ArrayAdapter resta sempre una visualizzazione sequenziale.
Forse meglio inflatare row con due textView in una delle quali mettere il campo testo mentre nell'altra i campo numero.

E come si inflata in questo modo più complesso?
Ed ecco il CustomAdapter!


Mentre ArrayAdapter è già una classe definita, per il CustomAdapter dobbiamo crearcela noi, una classe, quindi possiamo definire il costruttore.

Ma CustomAdapter estende ArrayAdapter? Non lo avrei mai pensato.
Dunque, che costruttore ha ArrayAdapter?
ArrayAdapter<String>(this,R.layout.row,R.id.textView,String[]). Giusto?
Sì, ma qui c'è la sintassi:
    public CustomAdapter(Context context, int textViewResourceId,
            Contatto [] objects) {
        super(context, textViewResourceId, objects);
    }
Sono solo tre parametri, che vengono rimandati al super, ossia alla classe ArrayAdapter.
Perché?
Rivediamo i costruttori di ArrayAdapter...

Credo che il costruttore che avevamo usato prima sia questo:
ArrayAdapter(Context context, int resource, int textViewResourceId, List objects)
in cui, a parte il context, vengono forniti un file XML di risorse, una TextView, un oggetto List.
Il costruttore usato in questa nuova sintassi, invece, è un Context, int, T[]
Faccio un elenco dei vari costruttori rimarcando i tipi dei parametri...
Context, int
Context, int, int
Context, int, T[]
Context, int, int, T[]
Context, int, List
Context, int, int, List
Quello di prima era a quattro parametri, di cui uno era un ArrayList, per cui apparteneva all'ultimo tipo; questo è a tre parametri di cui uno è un array, per cui appartiene al tipo del terzo.
Quando gli int sono due, il primo è relativo a un file XML, l'altro a una TextView.
Quando invece l'int è uno, è relativo soltanto al file XML, mentre quello alla TextView non è presente.
Dunque in questo caso si fornisce al costruttore della classe solo il layout e l'array di oggetti, o stringhe, o quello che sia.

Quindi viene overridato il metodo getView di ArrayAdapter.
Questo ha dei parametri fra cui position, che esprimerebbe la posizione nell'ambito dell'array di ogni elemento.
Quindi credo che debba venir chiamato a ogni elemento trovato nell'array che è stato fornito come parametro al costruttore.

Mi sembra che questo metodo, dati la posizione e una view già fornita dal sistema, trasformi questa view nella view da posizionare poi nella ListView/GridView. Normalmente, inflaterebbe il layout già fornito come parametro al costruttore e la textView, sempre fornita come parametro, quindi vi posizionerebbe l'elemento preso dall'array fornito come parametro.
Invece noi la manipoliamo. Facciamo ugualmente inflatare il layout, di questo individuiamo le textViews, e ci posizioniamo quello che riteniamo dell'elemento fornito nell'array.

Si può anche manipolare ArrayAdapter overridando in vario modo il suo metodo getView.


Ho molta confusione in testa.
Per prima cosa, ho poca esperienza circa gli array, le ArrayList, le LinkedList eccetera, e credo che sarà meglio dissipare i dubbi in materia.
Quelle maledette parentesi angolari mi creano un bel po' di confusione.

Fammi vedere se un oggetto può essere associato a un'ArrayList.
Ho una minuscola classe:
    class Elemento{
        public String parola;
        public int numero;
        public Elemento(String parola, int numero){
            this.parola=parola;
            this.numero=numero;
        }

    }
(senza setter e senza getter, così, semplice...)

Voglio costruire un array di elementi di questa classe.
Elemento[] arrayElementi= {new Elemento("Mario",3),new Elemento("Giuseppe",6)};
Ecco: ora posso usare un'ArrayList?
Vediamo:
        ArrayList<Elemento> lista=new ArrayList<Elemento>();
        lista.add(new Elemento("Mario",3));
        lista.add(new Elemento("Giuseppe",6)); 
Ecco: dunque io ho una duplice possibilità di costruire un array di elementi istanziati da una classe: mediante un semplice Array o mediante un'ArrayList.


Dunque posso usare ambedue i tipi di costruttore di ArrayAdapter, l'uno che impiega arrays e l'uno che impiega ArrayLists.

Nessun commento:

Posta un commento