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 (....));