Android 坚持;没有此类列错误“;将ListActivity与LoaderCallbacks一起使用时
我的问题很小,但我似乎找不到解决方案。下面是我的代码,然后我解释我的问题 气象活动类Android 坚持;没有此类列错误“;将ListActivity与LoaderCallbacks一起使用时,android,sql,sqlite,Android,Sql,Sqlite,我的问题很小,但我似乎找不到解决方案。下面是我的代码,然后我解释我的问题 气象活动类 public class MetersActivity extends ListActivity implements LoaderCallbacks<Cursor>{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setConten
public class MetersActivity extends ListActivity implements LoaderCallbacks<Cursor>{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.meters_list);
this.getListView().setDividerHeight(2);
fillData();
registerForContextMenu(getListView());
}
private void fillData() {
// Fields from the database (projection)
// Must include the _id column for the adapter to work
LoaderManager lm = getLoaderManager();
String[] dataColumns = {"_id ", " meterNumber " };
int[] meter = { R.id.meter_number_label};
adapter = new SimpleCursorAdapter(this, R.layout.meter_row,
null, dataColumns, meter, 0);
setListAdapter(adapter);
lm.initLoader(LOADER_ID, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int id,
Bundle args) {
String[] PROJECTION = new String[] { "_id ", " meterNumber "};
CursorLoader cursorLoader = new CursorLoader(MetersActivity.this,UserAccountsContentProvider.CONTENT_URI,PROJECTION, null, null, null);
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// A switch-case is useful when dealing with multiple Loaders/IDs
switch (loader.getId()) {
case LOADER_ID:
// The asynchronous load is complete and the data
// is now available for use. Only now can we associate
// the queried Cursor with the SimpleCursorAdapter.
adapter.swapCursor(data);
break;
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// data is not available anymore, delete reference
adapter.swapCursor(null);
}
}
我的日志猫输出
03-13 10:45:29.058: E/SQLiteLog(827): (1) no such column: meterNumber
03-13 10:45:29.158: E/AndroidRuntime(827): FATAL EXCEPTION: AsyncTask #1
03-13 10:45:29.158: E/AndroidRuntime(827): java.lang.RuntimeException: An error occured while executing doInBackground()
03-13 10:45:29.158: E/AndroidRuntime(827): at android.os.AsyncTask$3.done(AsyncTask.java:299)
03-13 10:45:29.158: E/AndroidRuntime(827): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
03-13 10:45:29.158: E/AndroidRuntime(827): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
03-13 10:45:29.158: E/AndroidRuntime(827): Caused by: android.database.sqlite.SQLiteException: no such column: meterNumber (code 1): , while compiling: SELECT _id , meterNumber FROM waterbills
03-13 10:45:29.158: E/AndroidRuntime(827): at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
问题
我正在尝试使用ContentProvider从SQLite检索数据,并将其显示为列表。我有一个实现LoaderCallbacks的列表活动。我检查了大量教程,甚至严格遵守了一些教程,但我的应用程序由于某种原因崩溃。我在主活动上有一个按钮,其中一个按钮用于显示客户端列表。当我单击该按钮时,我应该转到一个单独的活动,它向我显示名称列表,但它在单击带有“编译时无此列…”错误的按钮后崩溃
我有三张桌子,顾客桌、水表桌和水袋桌。meterNumber列可以在meters表中找到,但我注意到错误表明在waterbills表中找不到“meterNumber”列!所以我想知道为什么它首先引用了它,但我已经检查了代码,它似乎还可以。我也分别卸载了应用程序,增加了数据库版本,但仍然不起作用。有时,一双额外的眼睛可以帮助我们看到我们没有看到的东西。我真的非常感谢一些帮助
使用内容提供商类编辑
public class UserAccountsContentProvider extends ContentProvider{
private DatabaseHandler database;
// Used for the UriMacher
private static final int all_meters = 10;
private static final int single_meter = 20;
private static final int all_customers = 30;
private static final int single_customer = 40;
private static final int all_bills = 50;
private static final int single_bill = 60;
private static final String AUTHORITY = "com.isys.waterbillingsystem.contentprovider";
//table meters
private static final String METER_PATH = "meters";
public static final Uri CONTENT_URI_METER = Uri.parse("content://" + AUTHORITY
+ "/" + METER_PATH);
public static final String CONTENT_METER_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE
+ "/meters";
public static final String CONTENT_ITEM_METER_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
+ "/meter";
//table customers
private static final String CUSTOMERS_PATH = "customers";
public static final Uri CONTENT_URI_CUSTOMERS = Uri.parse("content://" + AUTHORITY
+ "/" + CUSTOMERS_PATH);
public static final String CONTENT_CUSTOMER_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE
+ "/customers";
public static final String CONTENT_ITEM_CUSTOMER_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
+ "/customer";
//table waterbills
private static final String BILL_PATH = "bills";
public static final Uri CONTENT_URI_WATERBILLS = Uri.parse("content://" + AUTHORITY
+ "/" + BILL_PATH);
private static final UriMatcher sURIMatcher = new UriMatcher(
UriMatcher.NO_MATCH);
static {
sURIMatcher.addURI(AUTHORITY, METER_PATH, all_meters);
sURIMatcher.addURI(AUTHORITY, METER_PATH + "/#", single_meter);
sURIMatcher.addURI(AUTHORITY, CUSTOMERS_PATH, all_customers);
sURIMatcher.addURI(AUTHORITY, CUSTOMERS_PATH + "/#", single_customer);
sURIMatcher.addURI(AUTHORITY, BILL_PATH, all_bills);
sURIMatcher.addURI(AUTHORITY, BILL_PATH + "/#", single_bill);
}
@Override
public boolean onCreate() {
try {
database = new DatabaseHandler(getContext());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = database.getWritableDatabase();
// Using SQLiteQueryBuilder instead of query() method
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(MeterTableDetails.TABLE_METERS);
queryBuilder.setTables(CustomerTableDetails.TABLE_CUSTOMERS);
queryBuilder.setTables(WaterBillTableDetails.TABLE_WATER_BILL);
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case all_meters:
break;
case single_meter:
// Adding the ID to the original query
String id = uri.getPathSegments().get(1);
queryBuilder.appendWhere(MeterTableDetails.METER_ID + "=" + id);
break;
case all_customers:
break;
case single_customer:
// Adding the ID to the original query
String id1 = uri.getPathSegments().get(1);
queryBuilder.appendWhere(CustomerTableDetails.KEY_CUSTOMER_ID + "=" + id1);
break;
case all_bills:
break;
case single_bill:
// Adding the ID to the original query
String id2 = uri.getPathSegments().get(1);
queryBuilder.appendWhere(WaterBillTableDetails.BILL_ID + "=" + id2);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, sortOrder);
// Make sure that potential listeners are getting notified
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase sqlDB = database.getWritableDatabase();
long id = 0;
switch (uriType) {
case all_meters:
id = sqlDB.insert(MeterTableDetails.TABLE_METERS, null, values);
break;
case all_customers:
id = sqlDB.insert(CustomerTableDetails.TABLE_CUSTOMERS, null, values);
break;
case all_bills:
id = sqlDB.insert(WaterBillTableDetails.TABLE_WATER_BILL, null, values);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(METER_PATH + "/" + id);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase db = database.getWritableDatabase();
switch (uriType) {
case all_meters:
break;
case single_meter:
String id = uri.getPathSegments().get(1);
selection = MeterTableDetails.METER_ID
+ "="
+ id
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
case all_customers:
break;
case single_customer:
String id1 = uri.getPathSegments().get(1);
selection = CustomerTableDetails.KEY_CUSTOMER_ID
+ "="
+ id1
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
case all_bills:
break;
case single_bill:
String id2 = uri.getPathSegments().get(1);
selection = WaterBillTableDetails.BILL_ID
+ "="
+ id2
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
int deleteCount;
deleteCount = db.delete(MeterTableDetails.TABLE_METERS, selection,
selectionArgs);
deleteCount = db.delete(CustomerTableDetails.TABLE_CUSTOMERS, selection,
selectionArgs);
deleteCount = db.delete(WaterBillTableDetails.TABLE_WATER_BILL, selection,
selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return deleteCount;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase db = database.getWritableDatabase();
switch (uriType) {
case all_meters:
break;
case single_meter:
String id = uri.getPathSegments().get(1);
selection = MeterTableDetails.METER_ID
+ "="
+ id
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
case all_customers:
break;
case single_customer:
String id1 = uri.getPathSegments().get(1);
selection = CustomerTableDetails.KEY_CUSTOMER_ID
+ "="
+ id1
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
case all_bills:
break;
case single_bill:
String id2 = uri.getPathSegments().get(1);
selection = WaterBillTableDetails.BILL_ID
+ "="
+ id2
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
int updateCount;
updateCount = db.update(MeterTableDetails.TABLE_METERS, values,
selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
updateCount = db.update(CustomerTableDetails.TABLE_CUSTOMERS, values, selection,
selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
updateCount = db.update(WaterBillTableDetails.TABLE_WATER_BILL, values, selection,
selectionArgs);
return updateCount;
}
}
因此,在表
waterbills
中没有MeterNumber
列:
private static final String CREATE_TABLE_WATERBILL = "create table "
+ TABLE_WATER_BILL
+ "("
+ BILL_ID + " integer primary key autoincrement, "
+ BILL_NUMBER + " integer, "
+ KEY_BILLING_DATE + " date, "
+ KEY_PREVIOUS_READING + " integer, "
+ KEY_CURRENT_READING+ " integer, "
+ KEY_DATEOF_READING + " date, "
+ KEY_CONSUMPTION + " integer, "
+ KEY_DUE_DATE + " date, "
+ KEY_BILL_ITEMS + " varchar, "
+ KEY_RATE + " integer, "
+ KEY_CHARGES + " integer, "
+ KEY_CONSUMPTION_PERIOD + " date, "
+ KEY_TOTAL_DUE + " integer, "
+ BILL_METER_ID + " integer not null, "
+ " FOREIGN KEY ("+BILL_METER_ID+") REFERENCES "+TABLE_CUSTOMERS+" ("+KEY_METER_ID+"));"
+ ");";
你在等什么
在数据提供程序中设置表,这些表将用于如下查询:
queryBuilder.setTables(MeterTableDetails.TABLE_METERS);
queryBuilder.setTables(CustomerTableDetails.TABLE_CUSTOMERS);
queryBuilder.setTables(WaterBillTableDetails.TABLE_WATER_BILL);
这是错误的。仅对水费单表进行查询。如果要从多个表中获取数据,请执行以下操作:
为什么你的列名周围有空格?如果我正确理解了你的问题,那么你的内容提供商似乎有问题。请发布该类的相关代码。@pskink因为本网站上其他人也有类似的“无此类列”问题,他们建议有些人在逗号后创建空格,这样查询就不会将其解释为加号后的一个单词。所以我决定也尝试一下。但显然这并不能解决我的问题。@MikeM。我刚刚添加了我的内容提供商类…嘿@MikkanRin不,我在水费账单表中没有该列..查询应该给我一个在水表中注册的所有水表编号的列表..这就是为什么在onCreate Loader中我输入“_id”和“meterNumber”列…那么为什么使用waterbills表来获取水表编号呢<代码>03-13 10:45:29.158:E/AndroidRuntime(827):原因:android.database.sqlite.SQLiteException:没有这样的列:meterNumber(代码1):,编译时:选择\u id,来自waterbills的meterNumber我不是..这就是问题..或者至少如果我是..那么我似乎找不到我使用waterbills获取meterNumber的代码中的确切位置..你能指出我在代码中的位置吗?…我刚刚添加了我的内容提供商类..对我来说似乎没问题..所以我不知道我在哪里引用waterbills表而不是米表…哇,谢谢你..太多@MIkkaRin我会马上这么做,并给你反馈..因为我这里有三个表,我会在一个表中有两个连接,像这样:queryBuilder.setTables(MeterTableDetails.table_米内部连接CustomerTableDetails.table_CUSTOMERS ON(MeterTableDetails.METER_ID=CustomerTableDetails.KEY_METER_ID));
queryBuilder.setTables(MeterTableDetails.TABLE_METERS);
queryBuilder.setTables(CustomerTableDetails.TABLE_CUSTOMERS);
queryBuilder.setTables(WaterBillTableDetails.TABLE_WATER_BILL);
queryBuilder.setTables(MeterTableDetails.TABLE_METERS INNER JOIN CustomerTableDetails.TABLE_CUSTOMERS ON (....));