我有一个数据库和内容提供商的应用程序。我正在关注教程,但尽管如此,我得到错误,无法摆脱它们。特别是当我尝试将初始(演示)数据添加到数据库时。以下是我得到的错误以及我使用的代码。
错误
当我安装应用程序(没有演示数据)时,我会收到以下信息:
跳过96帧!应用程序可能在其主线程上做了太多工作。 至少,应用程序运行。
每当我尝试添加演示数据时,应用程序会在开头显示相同的信息。当我带着从数据库中读取的项目列表进入屏幕时,它崩溃了。这是日志:
06-25 12:08:54.358: E/AndroidRuntime(4971): FATAL EXCEPTION: main
06-25 12:08:54.358: E/AndroidRuntime(4971): java.lang.RuntimeException: Unable to start activity ComponentInfo{….ItemListActivity}: java.lang.IllegalStateException: getDatabase called recursively
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.app.ActivityThread.access$600(ActivityThread.java:130)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.os.Handler.dispatchMessage(Handler.java:99)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.os.Looper.loop(Looper.java:137)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.app.ActivityThread.main(ActivityThread.java:4745)
06-25 12:08:54.358: E/AndroidRuntime(4971): at java.lang.reflect.Method.invokeNative(Native Method)
06-25 12:08:54.358: E/AndroidRuntime(4971): at java.lang.reflect.Method.invoke(Method.java:511)
06-25 12:08:54.358: E/AndroidRuntime(4971): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
06-25 12:08:54.358: E/AndroidRuntime(4971): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
06-25 12:08:54.358: E/AndroidRuntime(4971): at dalvik.system.NativeStart.main(Native Method)
06-25 12:08:54.358: E/AndroidRuntime(4971): Caused by: java.lang.IllegalStateException: getDatabase called recursively
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:204)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
06-25 12:08:54.358: E/AndroidRuntime(4971): at ….MyContentProvider.insert(MyContentProvider.java:83)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.content.ContentProvider$Transport.insert(ContentProvider.java:201)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.content.ContentResolver.insert(ContentResolver.java:864)
06-25 12:08:54.358: E/AndroidRuntime(4971): at ….DatabaseHelper.addItem(DatabaseHelper.java:78)
06-25 12:08:54.358: E/AndroidRuntime(4971): at ….DatabaseHelper.onCreate(DatabaseHelper.java:61)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:252)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:188)
06-25 12:08:54.358: E/AndroidRuntime(4971): at ….MyContentProvider.query(MyContentProvider.java:68)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.content.ContentProvider.query(ContentProvider.java:652)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.content.ContentProvider$Transport.query(ContentProvider.java:189)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.content.ContentResolver.query(ContentResolver.java:370)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.content.ContentResolver.query(ContentResolver.java:313)
06-25 12:08:54.358: E/AndroidRuntime(4971): at ….DatabaseHelper.getAllItems(DatabaseHelper.java:89)
06-25 12:08:54.358: E/AndroidRuntime(4971): at ….Items.getAllItems(Items.java:27)
06-25 12:08:54.358: E/AndroidRuntime(4971): at ….ItemListFragment.onCreate(ItemListFragment.java:26)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:796)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.app.BackStackRecord.run(BackStackRecord.java:635)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1397)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.app.Activity.performStart(Activity.java:5017)
06-25 12:08:54.358: E/AndroidRuntime(4971): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2032)
06-25 12:08:54.358: E/AndroidRuntime(4971): ... 11 more
代码
我有一个列表活动,其中包含非常标准的列表适配器,我发现它不相关。
Items
类请求数据库中的项目。
public class Items {
public static ArrayList<Item> getAllItems() {
return new DatabaseHelper().getAllItems();
}
…
}
数据库助手类:
public class DatabaseHelper extends SQLiteOpenHelper {
private ContentResolver contentResolver;
…
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.contentResolver = context.getContentResolver();
}
public DatabaseHelper() {
this(MyApplication.getContext());
}
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(SQL_CREATE_TABLE_ITEMS);
//addItem(Items.getDemoItem());
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(SQL_DELETE_TABLE_ITEMS);
onCreate(db);
}
public void addItem(Item item)
{
ContentValues values = new ContentValues();
values.put(…);
contentResolver.insert(MyContentProvider.CONTENT_URI, values);
}
public ArrayList<Item> getAllItems()
{
...
Cursor cursor = contentResolver.query(MyContentProvider.CONTENT_URI,
projection, null, null, null);
ArrayList<Item> items = new ArrayList<Item>();
while (cursor.moveToFirst())
{
cursor.moveToFirst();
…
items.add(item);
}
cursor.close();
return items;
}
}
以下是我使用的内容提供商:
public class MyContentProvider extends ContentProvider {
private DatabaseHelper dbHelper;
// Variables used for content URI
private static final String AUTHORITY = MyContentProvider.class.getCanonicalName();
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + DatabaseHelper.TABLE_ITEMS);
private static final int SINGLE_ITEM = 1;
private static final int ALL_ITEMS = 2;
private static final UriMatcher URI_MATCHER;
static
{
URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
URI_MATCHER.addURI(AUTHORITY, DatabaseHelper.TABLE_ITEMS, ALL_ITEMS);
URI_MATCHER.addURI(AUTHORITY, DatabaseHelper.TABLE_ITEMS + "/#", SINGLE_ITEM);
}
@Override
public boolean onCreate()
{
dbHelper = new DatabaseHelper(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder)
{
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(DatabaseHelper.TABLE_ITEMS);
switch (URI_MATCHER.match(uri)) {
case ALL_ITEMS:
break;
case SINGLE_ITEM:
queryBuilder.appendWhere(DatabaseHelper.ITEM_ID + "=" + uri.getLastPathSegment());
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
Cursor cursor = queryBuilder.query(dbHelper.getReadableDatabase(), projection, selection,
selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public Uri insert(Uri uri, ContentValues values)
{
switch (URI_MATCHER.match(uri)) {
case ALL_ITEMS:
long id = dbHelper.getWritableDatabase()
.insert(DatabaseHelper.TABLE_ITEMS, null, values);
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(CONTENT_URI + "/" + id);
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
}
有人能找到错误吗?我知道向数据库添加数据会导致它被递归调用,但我真的不知道如何避免这种情况。为什么我在主线程上有这么多东西?由于我无法在没有数据的情况下加载屏幕,因此使用异步任务读取数据库并没有多大意义。我不知道如何在另一个线程中初始化内容提供程序。