【发布时间】:2016-10-04 21:17:33
【问题描述】:
所以我正在尝试一些我认为应该非常简单和直接的东西。我正在尝试从我自己创建的 android 上的 Sqlite 数据库中加载一些数据。唯一的问题是我收到此错误:
W/MainActivity: onCreate started
W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
W/NotificationDbHelper: Column in cursor named: _id
W/NotificationDbHelper: Column in cursor named: title
W/NotificationDbHelper: Column in cursor named: additional
W/NotificationDbHelper: Column in cursor named: icon
W/MainActivity: onCreate ended
D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
[ 10-04 09:04:07.090 4272: 4272 D/ ]
HostConnection::get() New Host Connection established 0xad17b6a0, tid 4272
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: dk.simwir.lockscreennotifications, PID: 4272
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalArgumentException: Invalid column title
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:165)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)
at android.content.ContentResolver.query(ContentResolver.java:491)
at android.content.CursorLoader.loadInBackground(CursorLoader.java:64)
at android.content.CursorLoader.loadInBackground(CursorLoader.java:56)
at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:312)
at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:69)
at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:66)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
尝试从表中加载数据时。主要错误接缝是:Caused by: java.lang.IllegalArgumentException: Invalid column title。它声称该列无效,但正如您在我创建的日志输出中看到的那样,它似乎在那里:W/NotificationDbHelper: Column in cursor named: title。我已经从 android adb 访问了数据库并确认它存在:
在研究问题时,我发现的主要“修复”是我需要将其添加到投影地图中,但我尝试了,但仍然没有修复。
错误似乎不是直接发生在我的代码中,而是发生在后台线程中,因此日志输出很难查明错误。但是来自数据库的信息是在这段代码中加载的:
Cursor cursor = notificationDbHelper.getAllActiveNotifications();
if(cursor == null){
Log.e(TAG, "Cursor returned null");
Toast toast = Toast.makeText(getApplicationContext(), R.string.cursor_null_error, Toast.LENGTH_LONG);
toast.show();
}else if (cursor.getCount()==0){
Log.e(TAG, "Cursor returned empty");
Toast toast = Toast.makeText(getApplicationContext(), R.string.no_active_notifications, Toast.LENGTH_SHORT);
toast.show();
}else{
String[] fromColumns = {ActiveNotificationEntry.COLUM_NAME_TITLE, ActiveNotificationEntry.COLUM_NAME_ADDITIONAL_TEXT};
int[] toViews = {R.id.notification_title, R.id.notification_additional_text};
cursorAdapter = new SimpleCursorAdapter(this, R.id.simple_notification, cursor, fromColumns, toViews, 0);
notificationList.setAdapter(cursorAdapter);
}
与数据库交互的getAllActiveNotifications函数如下所示:
public Cursor getAllActiveNotifications(){
HashMap<String, String> myProjectionMap = new HashMap<String, String>();
myProjectionMap.put(ActiveNotificationEntry._ID, ActiveNotificationEntry._ID);
myProjectionMap.put(ActiveNotificationEntry.COLUM_NAME_TITLE, ActiveNotificationEntry.COLUM_NAME_TITLE);
myProjectionMap.put(ActiveNotificationEntry.COLUM_NAME_ADDITIONAL_TEXT, ActiveNotificationEntry.COLUM_NAME_ADDITIONAL_TEXT);
myProjectionMap.put(ActiveNotificationEntry.COLUM_NAME_ICON, ActiveNotificationEntry.COLUM_NAME_ICON);
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(ActiveNotificationEntry.TABLE_NAME);
queryBuilder.setProjectionMap(myProjectionMap);
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = queryBuilder.query(db,CURSOR_COLUMNS, null, null, null, null, null);
if (cursor!=null){
for(int i = 0; i < cursor.getColumnCount(); i++){
Log.w("NotificationDbHelper", "Column in cursor named: " + cursor.getColumnName(i));
}
cursor.moveToFirst();
return cursor;
}else {
Log.e("NotificationDbHelper", "Cursor returned null");
return null;
}
}
光标列数组包含以下内容:
public static final String[] CURSOR_COLUMNS = new String[]{
ActiveNotificationEntry._ID,
ActiveNotificationEntry.COLUM_NAME_TITLE,
ActiveNotificationEntry.COLUM_NAME_ADDITIONAL_TEXT,
ActiveNotificationEntry.COLUM_NAME_ICON};
该表是在与 getActiveNotification() 相同的文件中创建的。该文件扩展了 SQLiteOpenHelper,并在创建时包含:
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(NotificationContract.SQL_CREATE_ENTRIES);
}
这里引用的 SQL_CREATE_ENTRIES 常量是:
public static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + ActiveNotificationEntry.TABLE_NAME + " (" +
ActiveNotificationEntry._ID + " INTEGER PRIMARY KEY" + COMMA_SEP +
ActiveNotificationEntry.COLUM_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
ActiveNotificationEntry.COLUM_NAME_ICON + TEXT_TYPE + COMMA_SEP +
ActiveNotificationEntry.COLUM_NAME_ADDITIONAL_TEXT + TEXT_TYPE + " )";
我尝试了一个简单的 database.query 而不是 QueryBuilder,但结果相同:
Cursor cursor = db.query(ActiveNotificationEntry.TABLE_NAME, CURSOR_COLUMNS,null,null,null,null,null,null);
即使错误消息说它在“doInBackground()”中,此时也不应该有任何 asynkTasks 处于活动状态。
我收集了所有我认为与gist 相关的文件。 MainActivity 上面使用的信息位于第 87 行。
【问题讨论】:
-
可能是的,但是在此之前您是否运行过创建表查询?你能发布这个查询吗?