Autore Topic: SharedPref: Valori \"pazzi\" assegnati alla CheckBox  (Letto 526 volte)

Offline markus988

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy N7100 Note II
  • Sistema operativo:
    Windows 7
SharedPref: Valori \"pazzi\" assegnati alla CheckBox
« il: 21 Luglio 2013, 12:48:47 CEST »
0
Buongiorno a tutti, dunque provo prima ad inquadrare il discorso in modo da rendere più rapida la lettura (spero). Per lo stesso motivo riporto volutamente porzioni di codice dove io, sottolineo io, credo sia localizzato il problema (in caso contrario edito volentieri l'intero codice).
Ho una Activity e nel momento in cui premo il tasto option, dunque nell' onCreateOptionMenu() avvio un nuovo intento con una nuova Activity ( con il metodo startActivity() ) che contiene una ListView con un CustomAdapter di tipo "Row". La generica "row" della mia list contiene una icona, un testo, del sub-testo e una checkbox, proprio per questa checkbox io utilizzo delle SharedPreferences per memorizzare i "check" anche alla distruzione dell'activity ma tali "check" sono sballati.

Dunque la classe principale con la ListView, niente di eccezionale creo un array di Row e lo passo come adapter:
PS: Attenzione nel creare l'array utilizzo già il metodo updatePreferencesData in modo da caricare all'avvio i valori salvati.

Codice (Java): [Seleziona]
public class SettingsActivity extends Activity {

private ListView settingsList;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.settings_layout);
    ...
    settingsList = (ListView)findViewById(R.id.listView1);
        Row items_data[] = new Row[] {
            new Row(R.drawable.google, "Mia Locazione",
                    "Mostra il pulsante Mia Locazione",
                    updatePreferencesData("myLocFlag")),
            new Row(R.drawable.traffic, "Traffico",
                    "Informazioni sul traffico",
                    updatePreferencesData("trafficFlag")),
            new Row(R.drawable.satellite, "Satellite",
                    "Panoramica satellitare",
                    updatePreferencesData("satelliteFlag")),
            new Row(R.drawable.arrow, "Seguimi",
                    "Muove la telecamera durante gli spostamenti",
                    updatePreferencesData("followFlag")) };

    RowAdapter adapter = new RowAdapter(this, R.layout.listview_item_row,
            items_data);
    settingsList.setAdapter(adapter);

Il punto cruciale della questione, da quanto ne ho capito io, è nella classe RowAdapter in particolare nel OnCheckedChangeListener che a sua volta è contenuto nel metodo getView().

Codice (Java): [Seleziona]
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    // View myRow = convertView;
    RowHolder holder = null;

    if (convertView == null) {
        // LayoutInflater inflater = ((Activity)
        // context).getLayoutInflater();
        convertView = inflater.inflate(layoutResourceId, null);

        holder = new RowHolder();
        holder.imgIcon = (ImageView) convertView.findViewById(R.id.imgIcon);
        holder.txtText = (TextView) convertView.findViewById(R.id.txtText);
        holder.txtSubText = (TextView) convertView
                .findViewById(R.id.txtSubText);
        holder.checkBox = (CheckBox) convertView
                .findViewById(R.id.checkBox);

        convertView.setTag(holder);
    } else {
        holder = (RowHolder) convertView.getTag();
    }

    Row row = data[position];
    holder.txtText.setText(row.text);
    holder.imgIcon.setImageResource(row.icon);
    holder.txtSubText.setText(row.subtext);
    holder.checkBox.setChecked(row.check);

    holder.checkBox
            .setOnCheckedChangeListener(new OnCheckedChangeListener() {
                public void onCheckedChanged(CompoundButton buttonView,
                        boolean isChecked) {
                    // Log.e("WARN", "Sto scrivendo " + isChecked +
                    // " al posizione: " + position);
                    if (position == 0)
                        savePreferencesData("myLocFlag", isChecked);

                    if (position == 1)
                        savePreferencesData("trafficFlag", isChecked);

                    if (position == 2)
                        savePreferencesData("satelliteFlag", isChecked);

                    if (position == 3)
                        savePreferencesData("followFlag", isChecked);
                }
            });

    return convertView;
}

Infine riporto i metodi per salvare e leggere le preferenze (davvero molto semplici):

Codice (Java): [Seleziona]
private boolean updatePreferencesData(String key) {
    SharedPreferences prefs = getSharedPreferences("MyPref", Context.MODE_PRIVATE);
    boolean textData = prefs.getBoolean(key, false);
    Log.e("MAPLOG", "Reading: " + textData + " da: " + key );
    return textData;
}

Codice (Java): [Seleziona]
private void savePreferencesData(String key, boolean flag) {
    SharedPreferences prefs = context.getSharedPreferences("MyPref",
            Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = prefs.edit();
    editor.putBoolean(key, flag);
    Log.e("ROW", "Writing: " + flag + " in " + key);
    editor.commit();
}
« Ultima modifica: 21 Luglio 2013, 12:56:37 CEST da markus988 »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:SharedPref: Valori \"pazzi\" assegnati alla CheckBox
« Risposta #1 il: 21 Luglio 2013, 13:32:15 CEST »
0
Quando visualizzi la ListView la prima volta, cioè all'apertura activity, i check sono giusti?

Se non lo sono fai un log della base dati subito dopo la creazione (Row items_data[] = new Row[]...) così da vedere cosa c'è dentro i singoli items_data.

E poi se anche cambi i check nelle savedpreferences, la basi dei dati dell'adapter dove la cambi e refreshi l'adapter? Oppure la ricrei da zero ad ogni variazione delle preferences?
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline markus988

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy N7100 Note II
  • Sistema operativo:
    Windows 7
Re:SharedPref: Valori \"pazzi\" assegnati alla CheckBox
« Risposta #2 il: 21 Luglio 2013, 15:10:26 CEST »
0
Quando visualizzi la ListView la prima volta, cioè all'apertura activity, i check sono giusti?

Se non lo sono fai un log della base dati subito dopo la creazione (Row items_data[] = new Row[]...) così da vedere cosa c'è dentro i singoli items_data.

E poi se anche cambi i check nelle savedpreferences, la basi dei dati dell'adapter dove la cambi e refreshi l'adapter? Oppure la ricrei da zero ad ogni variazione delle preferences?

Dunque la prima volta in assoluto tutti i check sono false come impostato nel valore di default del metodo savePrefencesData() e restano così fino a quando non ne cambio uno (qualsiasi) quindi in sostanza fin quando non attivo il listener e di conseguenza il metodo savePrefencesData().

Non appena ne cambio uno succede una cosa particolare; mi rendo conto ora che forse avrei dovuto segnalarla nel primo post...ad ogni modo ogni "refresh" dei check (che effettuo ricreando tutto da zero) la spunta true sale di una posizione: provo a fare una esempio xk così non è chiaro:

situazione iniziale:
1 FALSE
2 FALSE
3 FALSE

poniamo che scelgo di checkare il secondo:
1 FALSE
2 TRUE
3 FALSE

Checkando il metodo save si è attivato grazie al listener.
Adesso chiudo settingActivity con il tasto back, quindi in sostanza viene invocato il metodo onStop() con annessi e connessi (spero di non sbagliare).

Riclicco sul tastino option della mainActivity quindi chiamo l' onCreate() di settingsActivity che dovrebbe aggiornare i valori scritti nelle preferencs e ottengo:
1 TRUE
2 FALSE
3 FALSE

chiudo e riapro senza cambiare nulla
1 FALSE
2 FALSE
3 TRUE

etc...

Quini tornando alla domanda, non sono giusti al primo avvio (escludendo il primo in assoluto in cui diciamo anche che non ci sono proprio).
Domando scusa per tutti i condizionali ma sono newbie >.<
« Ultima modifica: 21 Luglio 2013, 15:12:55 CEST da markus988 »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:SharedPref: Valori \"pazzi\" assegnati alla CheckBox
« Risposta #3 il: 21 Luglio 2013, 17:34:57 CEST »
0
Ho visto che hai messo dei Log.e() nelle funzioni di lettura e scrittura Preferences.

Provando a riprodurre l'anomalia, quale sequenza di letture/scritture vedi nel Log?
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline markus988

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy N7100 Note II
  • Sistema operativo:
    Windows 7
Re:SharedPref: Valori \\\"pazzi\\\" assegnati alla CheckBox
« Risposta #4 il: 21 Luglio 2013, 18:58:19 CEST »
0
Ho visto che hai messo dei Log.e() nelle funzioni di lettura e scrittura Preferences.

Provando a riprodurre l'anomalia, quale sequenza di letture/scritture vedi nel Log?

Dunque l'update (lettura) è corretto: stampa 4 volte immediatamente dopo l' onCreate().
Il save (scrittura) è completamente sballato, a volte 4 altre 7 l'ultima non le ho contate ma erano più di 10. Onestamente non riesco proprio a capire, l'idea è che la scrittura viene invocata una volta sola al cambio del check.

Sto aumentando il numero di log e cercando di utilizzare al meglio il debug, edito in caso di novità.

EDIT: Riporto un esempio di Log, dunque pare esserci una sequenza 4 letture poi 7 scritture (???) poi 4 letture e 8 scritture dopodichè si ripete, il tutto mentre io non faccio assolutamente nulla vado solo avanti e dietro con option e back. Il numero di scritture dovrebbe essere 4 in quel caso in quanto alla costruzione della pagina io invoco il .setChecked con parementro l'updatePreferences.

Codice (Java): [Seleziona]
07-21 19:05:56.220: E/SensorManager(13867): thread start
07-21 19:06:03.620: E/MAPLOG(13867): Sto leggendo: false da: myLocFlag
07-21 19:06:03.620: E/MAPLOG(13867): Sto leggendo: false da: trafficFlag
07-21 19:06:03.620: E/MAPLOG(13867): Sto leggendo: false da: satelliteFlag
07-21 19:06:03.620: E/MAPLOG(13867): Sto leggendo: true da: followFlag
07-21 19:06:03.650: E/ROW(13867): Sto scrivendo: true in satelliteFlag
07-21 19:06:03.695: E/ROW(13867): Sto scrivendo: false in followFlag
07-21 19:06:03.715: E/ROW(13867): Sto scrivendo: true in satelliteFlag
07-21 19:06:03.715: E/ROW(13867): Sto scrivendo: false in followFlag
07-21 19:06:03.745: E/ROW(13867): Sto scrivendo: true in satelliteFlag
07-21 19:06:03.835: E/ROW(13867): Sto scrivendo: false in followFlag
07-21 19:06:03.835: E/ROW(13867): Sto scrivendo: true in satelliteFlag
07-21 19:06:22.140: E/MAPLOG(13867): Sto leggendo: false da: myLocFlag
07-21 19:06:22.140: E/MAPLOG(13867): Sto leggendo: false da: trafficFlag
07-21 19:06:22.140: E/MAPLOG(13867): Sto leggendo: true da: satelliteFlag
07-21 19:06:22.140: E/MAPLOG(13867): Sto leggendo: false da: followFlag
07-21 19:06:22.165: E/ROW(13867): Sto scrivendo: true in trafficFlag
07-21 19:06:22.185: E/ROW(13867): Sto scrivendo: false in satelliteFlag
07-21 19:06:22.225: E/ROW(13867): Sto scrivendo: true in trafficFlag
07-21 19:06:22.230: E/ROW(13867): Sto scrivendo: false in satelliteFlag
07-21 19:06:22.250: E/ROW(13867): Sto scrivendo: true in trafficFlag
07-21 19:06:22.255: E/ROW(13867): Sto scrivendo: false in satelliteFlag
07-21 19:06:22.310: E/ROW(13867): Sto scrivendo: true in trafficFlag
07-21 19:06:22.315: E/ROW(13867): Sto scrivendo: false in satelliteFlag
07-21 19:06:47.810: E/MAPLOG(13867): Sto leggendo: false da: myLocFlag
07-21 19:06:47.810: E/MAPLOG(13867): Sto leggendo: true da: trafficFlag
07-21 19:06:47.810: E/MAPLOG(13867): Sto leggendo: false da: satelliteFlag
07-21 19:06:47.810: E/MAPLOG(13867): Sto leggendo: false da: followFlag
07-21 19:06:47.830: E/ROW(13867): Sto scrivendo: true in myLocFlag
07-21 19:06:47.850: E/ROW(13867): Sto scrivendo: false in trafficFlag
07-21 19:06:47.895: E/ROW(13867): Sto scrivendo: true in myLocFlag
07-21 19:06:47.895: E/ROW(13867): Sto scrivendo: false in trafficFlag
07-21 19:06:47.920: E/ROW(13867): Sto scrivendo: true in myLocFlag
07-21 19:06:47.920: E/ROW(13867): Sto scrivendo: false in trafficFlag
07-21 19:06:47.995: E/ROW(13867): Sto scrivendo: true in myLocFlag
07-21 19:06:47.995: E/ROW(13867): Sto scrivendo: false in trafficFlag

Continuo con il debug :(

EDIT2: Dunque qualcosa di interessante, se commento così TUTTO funziona perfettamente:

Codice (Java): [Seleziona]
        Row items_data[] = new Row[]
        {
            new Row(R.drawable.google, "Mia Locazione", "Mostra il pulsante Mia Locazione", updatePreferencesData("myLocFlag")),
            //new Row(R.drawable.traffic, "Traffico", "Informazioni sul traffico", updatePreferencesData("trafficFlag")),
            //new Row(R.drawable.satellite, "Satellite", "Panoramica satellitare", updatePreferencesData("satelliteFlag")),
            //new Row(R.drawable.arrow, "Seguimi", "Muove la telecamera durante gli spostamenti", updatePreferencesData("followFlag"))
        };

Se invece ne faccio anche solo 2 anche se non clicco nulla il primo if (quello con position==0) viene invocato SEMPRE 4 volte.

Codice (Java): [Seleziona]
        Row items_data[] = new Row[]
        {
            new Row(R.drawable.google, "Mia Locazione", "Mostra il pulsante Mia Locazione", updatePreferencesData("myLocFlag")),
            new Row(R.drawable.traffic, "Traffico", "Informazioni sul traffico", updatePreferencesData("trafficFlag")),
            //new Row(R.drawable.satellite, "Satellite", "Panoramica satellitare", updatePreferencesData("satelliteFlag")),
            //new Row(R.drawable.arrow, "Seguimi", "Muove la telecamera durante gli spostamenti", updatePreferencesData("followFlag"))
        };

Boh :/

Post unito: 22 Luglio 2013, 11:56:45 CEST
Auto-taggo come risolto.

Per futuri lettori il problema era l'altezza della ListView

Codice (XML): [Seleziona]
    <ListView
       android:id="@+id/listView1"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"  <----------------
       android:layout_below="@id/line"
       android:divider="#009966"
       android:dividerHeight="1dip" />

Codice (XML): [Seleziona]
    <ListView
       android:id="@+id/listView1"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_below="@id/line"
       android:divider="#009966"
       android:dividerHeight="1dip" />

Quel wrap_content costringeva a numerose chiamate del metodo getView() che sballavano i valori.
« Ultima modifica: 22 Luglio 2013, 11:56:46 CEST da markus988, Reason: Merged DoublePost »