非同期タスクがSQLiteデータベースにデータを挿入しようとするたびに、次の例外が発生します。
java.lang.IllegalStateException:getWritableDatabaseが再帰的に呼び出されました
データは、ダウンロード、変換、そして最後にデータを挿入するための個別の非同期タスクを実行するサービスによって生成されます。渡したコンテキストオブジェクトが正しいかどうかわかりません。ソースコードに追加したコメントに注意してください。以下では、関連するクラスと関数を追加しました。さらに詳しい情報が必要な場合はコメントを残してください。
public class CustomServiceHelper {
// This method gets called by the activities.
public static void loadData(Context context) {
Intent intent = new Intent(context, CustomService.class);
context.startService(intent);
}
}
..。
public class CustomService extends Service {
private void startStoringTask(Users users) {
// Passing the context of the service.
mStoringTask = new StoringTask(this);
Object[] params = { users };
mStoringTask.execute(params);
}
}
..。
public class UsersProvider extends ContentProvider {
@Override
public boolean onCreate() {
// Not sure if getContext() is correct.
mDatabase = new CustomDatabase(getContext());
return true;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
switch (URI_MATCHER.match(uri)) {
case URI_CODE_USERS:
long id = mDatabase.insertUsers(values);
// TODO: Not sure about the return value.
return ContentUris.withAppendedId(uri, id);
}
return null;
}
}
..。
public class CustomDatabase {
public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
CustomSQLiteOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(TABLE_USERS_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
throw new UnsupportedOperationException();
}
}
private CustomSQLiteOpenHelper mDatabaseHelper = null;
public CustomDatabase(Context context) {
// The context is passed in by the UsersProvider.
mDatabaseHelper = new CustomSQLiteOpenHelper(context);
}
public long insertUsers(ContentValues contentValues) {
return mDatabaseHelper.getWritableDatabase().insert(
CustomSQLiteOpenHelper.TABLE_USERS, null, contentValues);
}
}
..。
public class StoringTask extends AsyncTask<Object, Void, Boolean> {
private Context mContext = null;
public StoringTask(Context context) {
mContext = context;
}
@Override
protected Boolean doInBackground(Object... params) {
Users users = (Users)params[0];
return storeUser(users);
}
private boolean storeUsers(Users users) {
if (users == null) return false;
// Not sure if calling getContentResolver on this context is correct.
ContentResolver contentResolver = mContext.getContentResolver();
Iterator<User> iterator = users.iterator();
do {
User user = iterator.next();
storeUser(contentResolver, user);
}
while (iterator.hasNext());
return true;
}
private void storeUser(ContentResolver contentResolver, User user) {
ContentValues cv = new ContentValues(1);
cv.put(CustomDatabase.Contract.COLUMN_NAME, user.name);
contentResolver.insert(UsersProvider.Contract.URI_USERS, cv);
}
}
アプリケーションをデバッグモードで実行すると、メソッドのブロックのフレームワーククラスThreadPoolExecutor
になります。finally
runWorker()
編集:
これが完全な例外スタックトレースです。
java.lang.RuntimeException: An error occured while executing doInBackground()
android.os.AsyncTask$3.done(AsyncTask.java:200)
java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
java.util.concurrent.FutureTask.setException(FutureTask.java:124)
java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
java.util.concurrent.FutureTask.run(FutureTask.java:137)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
java.lang.Thread.run(Thread.java:1096)
Caused by: java.lang.IllegalStateException: getWritableDatabase called recursively
android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:81)
com.test.users.database.CustomDatabase.insertUsers(CustomDatabase.java:125)
com.test.users.database.CustomDatabase$CustomSQLiteOpenHelper.insertTestData(CustomDatabase.java:85)
com.test.users.database.CustomDatabase$CustomSQLiteOpenHelper.onCreate(CustomDatabase.java:60)
android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:106)
com.test.users.database.CustomDatabase.insertUsers(CustomDatabase.java:125)
com.test.users.contentprovider.UsersProvider.insert(UsersProvider.java:51)
android.content.ContentProvider$Transport.insert(ContentProvider.java:174)
android.content.ContentResolver.insert(ContentResolver.java:587)
com.test.users.tasks.StoringTask.storeFeature(StoringTask.java:82)
com.test.users.tasks.StoringTask.storeResponse(StoringTask.java:58)
com.test.users.tasks.StoringTask.doInBackground(StoringTask.java:32)
com.test.users.tasks.StoringTask.doInBackground(StoringTask.java:1)
android.os.AsyncTask$2.call(AsyncTask.java:185)
java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
CustomSQLiteOpenHelper.insertTestData()
を呼び出すメソッドについては触れませんでしたgetWritableDatabase()
。insertTestData()
のメソッドを呼び出しますCustomSQLiteOpenHelper.onCreate()
。クラッシュは、アプリケーションがまだデータベースを作成していないときはいつでも発生します。要約すると、hawaii.five-0は完全に正しかったです!