Autore Topic: Errore database.query(...)  (Letto 690 volte)

Offline Bimbonanni

  • Nuovo arrivato
  • *
  • Post: 15
  • Respect: 0
    • Google+
    • bimbonanni
    • MatteoHammer
    • Mostra profilo
    • Organici Musicali
  • Dispositivo Android:
    HTC One X & Samsung Galaxy Nexus
  • Sistema operativo:
    Linux Mint 14
Errore database.query(...)
« il: 28 Febbraio 2013, 20:47:40 CET »
0
Salve a tutti.
Ho postato questo problema in calce ad un Tutorial ma forse è più opportuno metterlo nella sezione Supporto Tecnico.
Riassumo: ho una semplicissima app che gestisce un DB di due tabelle e alla pressione di un bottone deve fare una Select per riempire uno Spinner con le stringhe trovate dentro la tabella.

L'accesso iniziale, al DB, la creazione delle tabelle e il riempimento di una di esse funziona; il problema sorge quando cerco di fare la Select.
Il codice della Activity principale è il seguente:
Codice (Java): [Seleziona]
public class Home extends Activity {

        private GestioneDB db;
       
        private static final int MENUITEM_COMANDO_1 = 1;
        private static final int MENUITEM_COMANDO_2 = 2;
       
        private static final int REQUEST_NOTE_SELECTION = 1;
       
        private static final int DIALOG_ALERT_ID = 1;
       
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_home);
               
                db = new GestioneDB(getApplicationContext());
               
                Button vedi = (Button)findViewById(R.id.vediPass);
               
                [...]
               
                Button add = (Button) findViewById(R.id.addPass);
                add.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) { startSubActivity(); }});    
       
                Button delete = (Button) findViewById(R.id.cancPass);
       
                [...]
       
        }
       
        private void startSubActivity() {
                db.open();
                Log.i("PassRem->Add", "Creo DB");      
                Intent intent = new Intent(this, Add.class);
                startActivity(intent);
        }
}
Il bottone 'add' invoca startSubActivity che chiama db.open() nella classe GestioneDB:
Codice (Java): [Seleziona]
public class GestioneDB {
       
    SQLiteDatabase db;
    DbHelper dbHelper;
    Context context;
       
        private static final String DB_NAME = "database";
        private static final int DB_VERSION = 1;
       
        public GestioneDB(Context context) {
                this.context = context;
                dbHelper = new DbHelper(context, DB_NAME, null, DB_VERSION);
        }

        public void open() {  //il database su cui agiamo è leggibile/scrivibile
             db = dbHelper.getWritableDatabase();
        }
Poi c'è la classe DbHelper con le operazioni di inserimento (la classe DbHelper è assieme a GestioneDB, nello stesso file *.java):
Codice (Java): [Seleziona]
ublic class DbHelper extends SQLiteOpenHelper {
               
                private ContentValues values1 = new ContentValues();
                private ContentValues values2 = new ContentValues();
                private ContentValues values3 = new ContentValues();

                public DbHelper(Context context, String name, CursorFactory factory, int version) {
                        super(context, name, factory, version);
                        // TODO Auto-generated constructor stub
                }

                @Override
                public void onCreate(SQLiteDatabase db) {
                        db.execSQL(CREA_TABELLA1);

                        values1.put("nome", "Account Mail");
                        db.insert(Categorie.TABLE, null, values1);
                       
                        values2.put("nome", "Account Internet");
                        db.insert(Categorie.TABLE, null, values1);     
                       
                        values3.put("nome", "Conto Banca");
                        db.insert(Categorie.TABLE, null, values3);
                       
                        db.execSQL(TABLE_CREATE);
                }
Finito il tutto, la Activity principale chiama Add.class (definito in startSubActivity() poco sopra), il cui codice è il seguente:
Codice (Java): [Seleziona]
public class Add extends Activity {
       
        private GestioneDB db;
        private SQLiteDatabase database;
        private ArrayAdapter<CharSequence> adapter;
        private String[] categorie = new String[0];
        private int i=0;
       
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_add);
               
                Button annulla = (Button) findViewById(R.id.annulla);
                Button reset = (Button) findViewById(R.id.resetta);
                Button add = (Button) findViewById(R.id.aggiungiPassword);
               
                //Query: SELECT nome FROM categoria
                String[] columns = {"nome"};
                Cursor c = database.query("categoria", columns, null, null, null, null, null); // SI PIANTA QUI!
               
                while (c.moveToNext()) {
                        categorie[i] = c.getString(1);
                        i++;
                }
               
                // Bottone Annulla. Il Listner termina la finestra con finish();
                annulla.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) {finish();}});
               
                //Bottone Reset che resetta i Campi dei TextField
                reset.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) { resettaCampi(); }});                      
               
                add.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) { addNewPassword(); }});      
        }
}
e l'applicazione si pianta su Cursor c = database.query("categoria", columns, null, null, null, null, null); perché ho l'impressione che database dia fastidio poiché non inizializzato, ma non so dove inizializzarlo  :-(

E inoltre (se commento il codice incriminato e l'app va avanti...), quando clicco sul bottone annulla, tornando all'activity principale (a seguito di finish(); ), questa si pianta (il Logcat mi dice Unable to destroy activity). Che sia per qualche oggetto o istanza che si comporta in modo bizzarro?

Il Logcat del piantamento della query è:
Codice: [Seleziona]
02-28 18:04:45.364: W/dalvikvm(31678): threadid=1: thread exiting with uncaught exception (group=0x414a9930)
02-28 18:04:45.372: E/AndroidRuntime(31678): FATAL EXCEPTION: main
02-28 18:04:45.372: E/AndroidRuntime(31678): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.main.passrem/com.main.passrem.Add}: java.lang.NullPointerException
02-28 18:04:45.372: E/AndroidRuntime(31678):         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at android.app.ActivityThread.access$600(ActivityThread.java:141)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at android.os.Handler.dispatchMessage(Handler.java:99)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at android.os.Looper.loop(Looper.java:137)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at android.app.ActivityThread.main(ActivityThread.java:5041)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at java.lang.reflect.Method.invokeNative(Native Method)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at java.lang.reflect.Method.invoke(Method.java:511)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at dalvik.system.NativeStart.main(Native Method)
02-28 18:04:45.372: E/AndroidRuntime(31678): Caused by: java.lang.NullPointerException
02-28 18:04:45.372: E/AndroidRuntime(31678):         at com.main.passrem.Add.onCreate(Add.java:43)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at android.app.Activity.performCreate(Activity.java:5104)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
02-28 18:04:45.372: E/AndroidRuntime(31678):         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
02-28 18:04:45.372: E/AndroidRuntime(31678):         ... 11 more
02-28 18:04:45.380: W/ActivityManager(389):   Force finishing activity com.main.passrem/.Add
02-28 18:04:45.387: W/ActivityManager(389):   Force finishing activity com.main.passrem/.Home
02-28 18:04:45.887: W/ActivityManager(389): Activity pause timeout for ActivityRecord{41d72870 u0 com.main.passrem/.Add}
Credo che il NullPointer sia database di database.query(ecc); a causa della mia poca esperienza, sono sicuro che tra tutti sti tipi database, SQLiteecc mi sono perso qualche inizializzazione o qualche costruttore mal messo.

Chiedo scusa per la lunghezza ma ho voluto essere il più dettagliato possibile per facilitare chi mi vorrà dare una mano  ;-)
Strumenti per lo sviluppo di Android:
- Eclipse con ADT ed SDK Versione 8
- Versione API: variabile...
- Come emulatori utilizzo direttamente i miei dispositivi Android

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:Errore database.query(...)
« Risposta #1 il: 28 Febbraio 2013, 20:58:48 CET »
0
Beh, dici bene, se database è null è normale ti esca NullPointerException.  :-)

Ogni activity è come un programma a sé stante, all'avvio devi re-inizializzare tutte le variabili. A meno che tu non ne tenga riferimento in un Singleton o in una estensione della classe Application (che alla fine internamente è come un singleton).

Nel tuo caso specifico ti basta ripetere quello che già fai nell'activity precedente.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Bimbonanni

  • Nuovo arrivato
  • *
  • Post: 15
  • Respect: 0
    • Google+
    • bimbonanni
    • MatteoHammer
    • Mostra profilo
    • Organici Musicali
  • Dispositivo Android:
    HTC One X & Samsung Galaxy Nexus
  • Sistema operativo:
    Linux Mint 14
Re:Errore database.query(...)
« Risposta #2 il: 28 Febbraio 2013, 21:10:58 CET »
0
A logica non fa una piega :)

Ho provato ad aggiungere le righe per reinizializzare:

Codice (Java): [Seleziona]
public class Add extends Activity {
       
        private GestioneDB db;
        private SQLiteDatabase database;
        private DbHelper dbh;
        private ArrayAdapter<CharSequence> adapter;
        private String[] categorie = new String[0];
        private int i=0;
       
        private static final String DB_NAME = "database";
        private static final int DB_VERSION = 1;
       
        public Add() {}
       
        public Add(Context c) {
                dbh = db.new DbHelper(c, DB_NAME, null, DB_VERSION);
        }
       
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_add);
               
                [b]db = new GestioneDB(getApplicationContext());    <----[/b]
                Log.i("PassRem->Add", "Rendo SCRIVIBILE");     

                [b]database = dbh.getWritableDatabase();  <----[/b]
               
                //ContentValues values = new ContentValues();
               
                Button annulla = (Button) findViewById(R.id.annulla);
                Button reset = (Button) findViewById(R.id.resetta);
                Button add = (Button) findViewById(R.id.aggiungiPassword);

                              [ il resto è invariato ]
Ma ovviamente mi si pianta su database = dbh.getWritableDatabase();  :D
Sempre NullPointerException


Post unito: 01 Marzo 2013, 12:09:20 CET
Ho risolto riscrivendo da capo il codice in maniera più semplice però ho un problema con Cursor.
Il codice è questo:

Codice (Java): [Seleziona]
public class Add extends Activity {
       
        private DbHelper helper;
        private SQLiteDatabase db;
       
        private ArrayAdapter<CharSequence> adapter;
        private String[] categorie = new String[3];
        private int i=0;
       
        private Cursor c = null;
       
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                helper = new DbHelper(this);
                setContentView(R.layout.activity_add);
                               
                Log.i("PassRem->Add", "Rendo SCRIVIBILE");     
                db = helper.getWritableDatabase();
               
                Button annulla = (Button) findViewById(R.id.annulla);
                Button reset = (Button) findViewById(R.id.resetta);
                Button add = (Button) findViewById(R.id.aggiungiPassword);

                Log.i("PassRem->Add", "Bottoni Creati");       
               
                //Query: SELECT nome FROM categoria
                db = helper.getReadableDatabase();
                String query = "SELECT nome FROM categoria";
                c = db.rawQuery(query, null);
               
                Log.i("PassRem->Add->Cursore", "Numero righe: "+c.getCount());
                Log.i("PassRem->Add->Cursore", "Numero colonne: "+c.getColumnCount());
                Log.i("PassRem->Add->Cursore", "Nome colonna: "+c.getColumnName(0));
               
                c.moveToFirst();
                Log.i("PassRem->Add", "Sto per entrare nel WHILE");    
                while (c.moveToNext()) {
                        categorie[i] = c.getString(1);
                        Log.i("Nel while", "Valore di i: "+i);
                        i++;
                }              
                Log.i("PassRem->Add", "Preso da DB");  
        }
}

La query funziona, infatti la stampa nel Log è:
Codice: [Seleziona]
03-01 11:56:23.876: I/PassRem->Add(17116): Bottoni Creati
03-01 11:56:23.876: I/PassRem->Add->Cursore(17116): Numero righe: 3
03-01 11:56:23.876: I/PassRem->Add->Cursore(17116): Numero colonne: 1
03-01 11:56:23.876: I/PassRem->Add->Cursore(17116): Nome colonna: nome
03-01 11:56:23.876: I/PassRem->Add(17116): Sto per entrare nel WHILE
Quindi il cursore trova le righe (sono effettivamente 3) e la colonna che mi interessa.
Il problema è nel While e infatti stampa:
Codice: [Seleziona]
03-01 11:56:23.876: E/CursorWindow(17116): Failed to read row 0, column 1 from a CursorWindow which has 3 rows, 1 columns.
03-01 11:56:23.907: E/AndroidRuntime(17116): FATAL EXCEPTION: main
03-01 11:56:23.907: E/AndroidRuntime(17116): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.main.passrem/com.main.passrem.Add}: java.lang.IllegalStateException: Couldn't read row 0, col 1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.app.ActivityThread.access$600(ActivityThread.java:141)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.os.Handler.dispatchMessage(Handler.java:99)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.os.Looper.loop(Looper.java:137)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.app.ActivityThread.main(ActivityThread.java:5041)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at java.lang.reflect.Method.invokeNative(Native Method)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at java.lang.reflect.Method.invoke(Method.java:511)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at dalvik.system.NativeStart.main(Native Method)
03-01 11:56:23.907: E/AndroidRuntime(17116): Caused by: java.lang.IllegalStateException: Couldn't read row 0, col 1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.database.CursorWindow.nativeGetString(Native Method)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.database.CursorWindow.getString(CursorWindow.java:434)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at com.main.passrem.Add.onCreate(Add.java:60)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.app.Activity.performCreate(Activity.java:5104)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
03-01 11:56:23.907: E/AndroidRuntime(17116):         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
03-01 11:56:23.907: E/AndroidRuntime(17116):         ... 11 more
Perché couldn't read row 0? Cosa lo turba?
Se invece tolgo il c.getString(int) nel While non ci va proprio e stampa direttamente il Log fuori...
Non riesco veramente a capire dove sta il problema, non so se è un problema di indici o di cursore non inizializzato correttamente...
« Ultima modifica: 01 Marzo 2013, 12:09:20 CET da Bimbonanni, Reason: Merged DoublePost »
Strumenti per lo sviluppo di Android:
- Eclipse con ADT ed SDK Versione 8
- Versione API: variabile...
- Come emulatori utilizzo direttamente i miei dispositivi Android