У вас есть какие-либо потоки вашего собственного творения? Некоторый код, который может быть сброшен mSQLDBreader
другим способом. Возможно, этот поток иногда запускает и уничтожает значение mSQLDBreader перед его использованием?
Вы когда-нибудь видели это на эмуляторе под управлением 2.3.x?
Я посмотрел код google для getReadableDatabase, и я не вижу способа вернуть его. Если вы заинтересованы, подробности ниже. Основываясь на том, что я вижу, я бы заподозрил либо многопоточную ошибку в вашем коде, либо ошибку, внесенную настройками в код андроида производителем тестируемых устройств (если это даже правдоподобно.)
Gory details Все пути через getReadableDatabase вызывают методы на возвращаемом объекте после его создания. Таким образом, значение не может быть нулевым в этой точке. В противном случае NPE будет поднят изнутри.
Ниже приведен фрагмент кода 2.3.6 для getReadableDatabase. Фактический источник доступен по адресу grepcode.
public synchronized SQLiteDatabase getReadableDatabase() {
if (mDatabase != null && mDatabase.isOpen()) {
return mDatabase; // The database is already open for business
}
if (mIsInitializing) { /* snip throw ISE */ }
try {
return getWritableDatabase();
} catch (SQLiteException e) {
// snip : throws or falls through below
}
SQLiteDatabase db = null;
try {
mIsInitializing = true;
String path = mContext.getDatabasePath(mName).getPath();
db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY);
// *** next line calls method on db. NPE would be here if db was null at this point. ***
if (db.getVersion() != mNewVersion) {
// snip throw.
}
onOpen(db);
Log.w(TAG, "Opened " + mName + " in read-only mode");
mDatabase = db;
return mDatabase;
} finally {
// snip : not relevant
}
}
Обратите внимание, что getReadableDatabase обычно возвращает результат getWritableDatabase. Он выглядит следующим образом:
public synchronized SQLiteDatabase getWritableDatabase() {
if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
return mDatabase; // The database is already open for business
}
if (mIsInitializing) {
throw new IllegalStateException("getWritableDatabase called recursively");
}
// snip comment about locking
boolean success = false;
SQLiteDatabase db = null;
if (mDatabase != null) mDatabase.lock();
try {
mIsInitializing = true;
if (mName == null) {
db = SQLiteDatabase.create(null);
} else {
db = mContext.openOrCreateDatabase(mName, 0, mFactory);
}
int version = db.getVersion(); // ** method called on result!
// snip block that has more method calls and never nulls out db
onOpen(db);
success = true;
return db;
} finally {
// snip
mDatabase = db;
// snip rest of finally block that isn't relevant.
}
}
Наконец, важно отметить, что оба эти методы, а также близкий метода SqliteOpenHelper, помечаются синхронизацией, так что нет никакого способа один способ громить состояние других, если у вас есть несколько потоков, призывающих эти методы в то же время ..