2010-08-15 2 views
6

Я новичок в платформе Android, и я не могу пройти первую базу с помощью SQLite.Продолжайте получать NullPointerExceptions при попытке вызвать getWritableDatabase()

Я пытаюсь создать очень простое приложение, в котором есть окно поиска EditText, которое при нажатии клавиши выполняет поиск типа% word% в базе данных SQLite для текста, введенного в поле EditText, и отображает результаты в ListView.

N.B. приведенный ниже код включал отладочную и прокомментированную версию кода, извините, что я еще не смог его очистить.

Активировать является

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; 

пропущено, но вы получите идею.

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); 

} 

} 

SQLite базы данных обрабатывается 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); 
      } 
     } 
} 

Теперь каждый раз, когда "база данных = helper.getWritableDatabase();" называется сбоем приложения с исключением NullPointerException. Мне удалось проследить ошибку до метода onCreate OpenHelper и «db.beginTransaction();» линия.

Что мне не хватает?

+0

Также для справки (мой, если никто не elses) 'db.endTransaction();' заставляет onCreate терпеть неудачу (и терпеть неудачу молча), вызывая ошибку времени выполнения в 'OpenHelper helper = new OpenHelper (myContext);' и не записывая любые таблицы в базу данных (и, таким образом, вызывают дополнительное SQLException при следующем вызове). Надеюсь, что эта остановка - это кто-то другой, теряющий день, отслеживающий ее (или просто меня в следующий раз, когда я напишу класс базы данных). –

ответ

8

На самом деле вам не нужно начинать транзакцию по методу onCreate для помощника. Попробуйте удалить все из метода, кроме db.execSQL(CREATE_TABLE_FEEDS);

Обновление: Я смог повторить проблему.

Переместить инициализацию поля fishDb на onCreate() способ действия после этого исчезнет. Похоже, что не стоит начинать инициализацию db до вызова функции onCreate.

Таким образом, вместо

fishDB fishDb = new fishDB(getApplicationContext()); 

сделать

fishDB fishDb; 

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

Спасибо за подсказку, но, к сожалению, это не соответствует этой проблеме. –

+0

Обновленный ответ. –

+0

Спасибо за обновление.и да, это исправлено, я был настолько одержим, что это проблема в классе db, который мне никогда не приходил в голову, это может быть связано с первоначальным вызовом. N.B. другим "Контекст = getApplicationContext();" также не работает, потому что вы не можете вызвать getApplicationContext() вне процедуры. использовать «Контекст, который = это»; вместо. –

2

Следующий код является производным от оригинальной Android Notepad учебник:

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 
} 

Вы бы создать экземпляр в вашей деятельности OnCreate() и возможно open() в 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()); 
    } 
} 

Надеюсь, что это поможет.

EDIT: используйте «_id» вместо «feed_id» для первичного ключа.

+0

Кроме того, не забудьте ознакомиться с документами Android по использованию ядра. Поиск: http://developer.android.com/guide/topics /search/index.html –

Смежные вопросы