IllegalArgumentException:列无效

这里是logcat:

01-15 16:06:03.622: ERROR/AndroidRuntime(22300): Uncaught handler: thread main exiting due to uncaught exception 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mohit.geo2do/com.mohit.geo2do.activities.TaskEdit}: java.lang.IllegalArgumentException: Invalid column due_date 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.app.ActivityThread.access$2200(ActivityThread.java:119) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.os.Handler.dispatchMessage(Handler.java:99) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.os.Looper.loop(Looper.java:123) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.app.ActivityThread.main(ActivityThread.java:4363) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at java.lang.reflect.Method.invokeNative(Native Method) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at java.lang.reflect.Method.invoke(Method.java:521) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:862) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at dalvik.system.NativeStart.main(Native Method) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): Caused by: java.lang.IllegalArgumentException: Invalid column due_date 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.database.sqlite.SQLiteQueryBuilder.computeProjection(SQLiteQueryBuilder.java:508) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.database.sqlite.SQLiteQueryBuilder.buildQuery(SQLiteQueryBuilder.java:356) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:309) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:266) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at com.mohit.geo2do.provider.TasksProvider.query(TasksProvider.java:174) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.content.ContentProvider$Transport.query(ContentProvider.java:130) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.content.ContentResolver.query(ContentResolver.java:202) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at com.mohit.geo2do.activities.TaskEdit.onCreate(TaskEdit.java:105) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 01-15 16:06:03.657: ERROR/AndroidRuntime(22300): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459) 

与之相关的行是:

 private Cursor task; private Uri uri; private String[] PROJECTION { Tasks._ID, Tasks.TITLE, Tasks.COMPLETED, Tasks.DUE_DATE, Tasks.IMPORTANCE, Tasks.NOTES }; ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.edit_task); ... uri = getIntent().getData(); task = getContentResolver().query(uri, PROJECTION, null, null, null); } ... 

可能是什么问题呢? 数据库创build得很好。 有没有其他的代码你需要看?

更新:
我非常确定这个列存在。 我用这个查询数据库:

 Cursor c = db.rawQuery("SELECT * FROM tasks LIMIT 1", null); for (int i = 0; i < c.getColumnNames().length; i++) { Log.v(TAG, c.getColumnNames()[i]); } 

在LogCat中:

 01-15 16:52:07.857: VERBOSE/TasksProvider(24325): Creating database... 01-15 16:52:07.862: VERBOSE/TasksProvider(24325): _id 01-15 16:52:07.862: VERBOSE/TasksProvider(24325): title 01-15 16:52:07.862: VERBOSE/TasksProvider(24325): completed 01-15 16:52:07.862: VERBOSE/TasksProvider(24325): due_date 01-15 16:52:07.862: VERBOSE/TasksProvider(24325): notes 01-15 16:52:07.862: VERBOSE/TasksProvider(24325): importance 

所以列存在。

该列无疑存在于您的数据库中,但如果您没有将该列添加到投影映射中 ,您将看到“无效列”错误。 您可以通过查询生成器对象添加投影映射,如下所示:

 // The projection map is a hashmap of strings HashMap<String, String> MyProjectionMap; MyProjectionMap = new HashMap<String, String>(); // Add column mappings to the projection map MyProjectionMap.put(Tasks._ID, Tasks._ID); MyProjectionMap.put(Tasks.TITLE, Tasks.TITLE); [...] SQLiteQueryBuilder qb; qb.setTables("tasks"); qb.setProjectionMap(MyProjectionMap) // Then do your query Cursor c = qb.query(db, projection, ...) 

要了解发生了什么,请查看SQLiteQueryBuilder类的源代码,您将看到以下内容:

 private String[] computeProjection(String[] projectionIn) { if (projectionIn != null && projectionIn.length > 0) { if (mProjectionMap != null) { [...] for (int i = 0; i < length; i++) { String userColumn = projectionIn[i]; String column = mProjectionMap.get(userColumn); [...] if (!mStrictProjectionMap && ( userColumn.contains(" AS ") || userColumn.contains(" as "))) { /* A column alias already exist */ projection[i] = userColumn; continue; } throw new IllegalArgumentException("Invalid column " + projectionIn[i]); } } [...] 

基本上,它将在投影中检查你要求的列与“允许”列的列表,你可以看到,如果地图不包含投影中的列,它将抛出一个IllegalArgumentException,就像你看到的那样。 (我想像这个检查地图是一个安全function,以防止滥用你的内容提供者的基于SQL的攻击,但这只是一个猜测。)

另请注意,如果在查询生成器中设置“严格”投影映射:

 qb.setStrictProjectionMap(true); 

那么在这种情况下,它期望你知道确切的列名称…如果你没有设置它,它会检查“AS”列别名 – 我认为这解释了你发现的“奇怪的修复”。

希望这可以帮助。

我发现了一个奇怪的修复。 在String[] PROJECTION 。 你必须做:

 private String[] PROJECTION { Tasks._ID, Tasks.TITLE, Tasks.COMPLETED, Tasks.DUE_DATE + " as " + Tasks.DUE_DATE, Tasks.IMPORTANCE + " as " + Tasks.DUE_DATE, Tasks.NOTES + " as " + Tasks.NOTES }; 

您是否在内容提供商的投影图中添加了相对于此列的表格? 我希望这有帮助。