2010-08-15 14 views
6

Sono nuovo nel framework Android e non riesco a superare la prima base con SQLite.Continua a ricevere NullPointerExceptions quando tenti di chiamare getWritableDatabase()

Sto provando a creare un'applicazione molto semplice che ha una casella di ricerca Modifica testo, che quando si preme un tasto esegue una ricerca% Like% di parole su un database SQLite per il testo inserito nella casella EditText e visualizza i risultati in un ListView.

N.B. il codice qui sotto includeva il debug e il codice commentato, mi spiace non aver ancora finito di pulirlo.

L'Attiva è

public class sustainable_fish extends Activity { 

private String keycodeToAscii(int arg2){ 

    String retvar = ""; 

    switch(arg2){ 
    case KeyEvent.KEYCODE_A: retvar = "a";break; 
    case KeyEvent.KEYCODE_B: retvar = "b";break; 

snipped, ma si ottiene l'idea.

case KeyEvent.KEYCODE_RIGHT_BRACKET: retvar = ")";break; 
    default: retvar = ""; break; 
    }; 
    return retvar; 

} 



Context that = getApplicationContext(); 
fishDB dh = new fishDB(getApplicationContext()); 


private OnKeyListener search = new OnKeyListener() { 

    public boolean onKey(View arg0, int arg1, KeyEvent arg2) { 


     @SuppressWarnings("unused") 
     Cursor cur = null; 
     String searchData; 
     EditText myEditText = (EditText) findViewById(R.id.fish_search); 
     CharSequence edit_text_value = myEditText.getText(); 
     searchData = edit_text_value.toString(); 
     searchData = searchData + keycodeToAscii(arg2.getKeyCode()); 
     Log.d("onKey", "searchData = "+searchData); 
     /* 
     Commented out because as the database doesn't work, so theirs no point just yet searching. 

     cur = fish.search(searchData); 
     if (cur != null) 
     { 
      String[] displayFields = new String[] {cur.getString(2), 
        cur.getString(1)}; 

      int[] displayViews = new int[] { R.id.fish_rank, 
        R.id.fish_name}; 

      SimpleCursorAdapter adapter = new SimpleCursorAdapter(that, 
        R.layout.text_list, cur, 
        displayFields, displayViews); 

      ListView myList=(ListView)findViewById(android.R.id.list); 

      myList.setAdapter(adapter); 
     } 
     */ 

     return false; 
    } 

}; 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.main); 
    EditText searchBar = (EditText) findViewById(R.id.fish_search); 
    searchBar.setOnKeyListener(search); 

} 

} 

Il database SQLite è gestita da fishDB

public class fishDB { 

public static final String DATABASE_NAME = "fish.db3"; 
public static final int DATABASE_VERSION = 1; 
private SQLiteDatabase database; 
private Context myContext; 
private static boolean booFirstrun = false; 

fishDB(Context inContext){ 
    myContext = inContext; 
    OpenHelper helper = new OpenHelper(myContext); 
    Log.w("fishDB", "Called OpenHelper"); 

      // Here be the problem... 

    database = helper.getWritableDatabase(); 

} 

public boolean firstRun(){ 
    return booFirstrun; 
} 


    private static class OpenHelper extends SQLiteOpenHelper { 

     private static final String CREATE_TABLE_FEEDS = "create table feeds (feed_id integer primary key autoincrement, " 
      + "title text not null, url text not null);"; 

      OpenHelper(Context context) { 
      super(context, DATABASE_NAME, null, DATABASE_VERSION); 
      Log.w("OpenHelper", "Called superconstructor"); 
      } 

      @Override 
      public void onCreate(SQLiteDatabase db) { 
       try { 
       Log.w("OpenHelper", "in onCreate"); 
       booFirstrun = true; 
       Log.w("OpenHelper", "set booFirstrun"); 
       db.beginTransaction(); 
       Log.w("OpenHelper", "db.beginTransaction"); 
       try { 
        // Create tables and test data 
        db.execSQL(CREATE_TABLE_FEEDS); 
        Log.w("OpenHelper", "execSQL"); 
        db.setTransactionSuccessful(); 
        Log.w("OpenHelper", "setTransactionSuccessful"); 
       } catch (SQLException e) { 
        Log.e("Error creating tables and debug data", e.toString()); 
        throw e; 
       } finally { 
        db.endTransaction(); 
       } 
       } catch (Exception e) { 
        Log.e("OpenHelper", e.toString()); 
       } finally { 
       Log.w("OpenHelper", "out of onCreate"); 
       } 
      } 

      @Override 
      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
      Log.w("OpenHelper", "Upgrading database, this will drop tables and recreate."); 
      onCreate(db); 
      } 
     } 
} 

Ora ogni volta "database = helper.getWritableDatabase();" si chiama l'app si blocca con una NullPointerException. Sono riuscito a rintracciare l'errore nel metodo onCreate di OpenHelper e in "db.beginTransaction();" linea.

Cosa mi manca?

+0

Anche per riferimento (il mio se non c'è nessun altro) 'db.endTransaction();' fa fallire (e fallisce silenziosamente) onCreate causando un errore di runtime in 'OpenHelper helper = new OpenHelper (myContext);' e non sta scrivendo qualsiasi tabella al database (e quindi causando un'ulteriore SQLException alla prossima chiamata). Spero che questo stop sia un altro sprecando un giorno a rintracciarlo (o solo a me la prossima volta che scrivo una classe Database) –

risposta

8

In realtà non è necessario avviare la transazione sul metodo onCreate dell'helper. Prova a rimuovere tutto dal metodo tranne db.execSQL(CREATE_TABLE_FEEDS);

Aggiornamento: Sono stato in grado di ripetere il problema.

Spostare l'inizializzazione del campo fishDb sul metodo di attività onCreate() dopo che l'errore scompare. Sembra che non sia una buona idea avviare l'inizializzazione del db prima che venga richiamato onCreate.

Così, invece di

fishDB fishDb = new fishDB(getApplicationContext()); 

fare

fishDB fishDb; 

onCreate(){ 
    super.onCreate(); 
    fishDb = new fishDB(getApplicationContext()); 
    .... //init listener, query db etc.. 
} 
+0

Grazie per il suggerimento, ma purtroppo non si adatta al problema. –

+0

Risposta aggiornata. –

+0

Grazie per l'aggiornamento.e sì che è stato risolto, ero così ossessionato dal fatto che si trattava di un problema nella classe db che non mi era mai venuto in mente che potesse essere un problema con la chiamata iniziale. N.B. ad altri "Contesto che = getApplicationContext();" inoltre non funziona perché non è possibile chiamare getApplicationContext() al di fuori di una procedura. usa "Contesto che = questo;" anziché. –

2

Il seguente codice è derivato da quello originale di Android Agenda tutorial:

public class FishDb { 

private static final String TAG = "FishDb"; 
private DatabaseHelper mDbHelper; 
private SQLiteDatabase mDb; 

private static final String CREATE_TABLE_FEEDS = "create table feeds (_id integer primary key autoincrement, " 
     + "title text not null, url text not null);"; 

public static final String DATABASE_NAME = "fish.db3"; 
public static final String DATABASE_TABLE = "feeds"; 
private static final int DATABASE_VERSION = 1; 

private final Context mCtx; 

private static class DatabaseHelper extends SQLiteOpenHelper { 

    DatabaseHelper(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 

     db.execSQL(CREATE_TABLE_FEEDS); 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     Log.w(TAG, "Upgrading database from version " + oldVersion + " to " 
       + newVersion + ", which will destroy all old data"); 
     db.execSQL("DROP TABLE IF EXISTS feeds"); 
     onCreate(db); 
    } 
} 

public DbAdapter(Context ctx) { 
    this.mCtx = ctx; 
} 

public DbAdapter open() throws SQLException { 
    mDbHelper = new DatabaseHelper(mCtx); 
    mDb = mDbHelper.getWritableDatabase(); 
    return this; 
} 

public void close() { 
    mDbHelper.close(); 
} 

// ... The helper methods 
} 

si farebbe istanziare nella tua Attività onCreate() e possibilmente open() in onResume(), close() on onPause():

private FishDb mDbHelper; 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    mDbHelper = new FishDb(this); 
} 

@Override 
public void onResume() { 
    super.onResume(); 
    try{ 
     mDbHelper.open(); 
    } catch(Exception e){ 
     Log.e("onResume", e.toString()); 
    } 
} 

@Override 
public void onPause() { 
    super.onPause(); 
    try{ 
     mDbHelper.close(); 
    } catch(Exception e){ 
     Log.e("onPause", e.toString()); 
    } 
} 

Spero che questo aiuti.

MODIFICA: utilizzare "_id" anziché "feed_id" per la chiave primaria.

+0

Inoltre, assicurati di controllare i documenti Android utilizzando la ricerca principale: http://developer.android.com/guide/topics /search/index.html –

Problemi correlati