【问题标题】:App Crash while using External Sqlite with SimpleCursor Adapter使用带有 SimpleCursor 适配器的外部 Sqlite 时应用程序崩溃
【发布时间】:2015-10-15 10:59:37
【问题描述】:

在学习了这么多教程之后,我现在正在创建一个应用程序

应用程序包含一个外部 sqlite 数据库。现在,当我尝试显示我的应用程序崩溃时,我试图在列表视图中显示第一列。当我签入 logcat 时,它只是说 column '_id ' 不存在但在我的数据库中我没有像 column_id 这样的列请帮助这里是我的代码如下

我在 SqliteManager 中的 Create 语句

CREATE TABLE "Ayervedic" ("Item No" NUMERIC NOT NULL , "Title" VARCHAR NOT NULL , "Subcategory" VARCHAR NOT NULL , "Details" VARCHAR NOT NULL , "Images" VARCHAR NOT NULL , PRIMARY KEY ("Item No", "Title", "Subcategory", "Details", "Images"))

数据库类

public class SqlLiteDbHelper extends SQLiteOpenHelper {

// Database Version
private static final int DATABASE_VERSION = 1;

// Database Name
private static final String DATABASE_NAME = "Ayervedic.sqlite";
private static final String DB_PATH_SUFFIX = "/databases/";
static Context ctx;

public SqlLiteDbHelper(Context context) {

    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    ctx = context;
}
public void CopyDataBaseFromAsset() throws IOException {

    InputStream myInput = ctx.getAssets().open(DATABASE_NAME);

    // Path to the just created empty db
    String outFileName = getDatabasePath();

    // if the path doesn't exist first, create it
    File f = new File(ctx.getApplicationInfo().dataDir + DB_PATH_SUFFIX);
    if (!f.exists())
        f.mkdir();

    // Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);


    // transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);

    }
    // Close the streams

    myOutput.flush();
    myOutput.close();
    myInput.close();

}

private static String getDatabasePath() {

    return ctx.getApplicationInfo().dataDir + DB_PATH_SUFFIX + DATABASE_NAME;

}

public SQLiteDatabase openDataBase() throws SQLException {

    File dbFile = ctx.getDatabasePath(DATABASE_NAME);
    if (!dbFile.exists()) {
        try {
            CopyDataBaseFromAsset();

            System.out.println("Copying sucess from Assets folder");

        } catch (IOException e) {

            throw new RuntimeException("Error creating source database", e);

        }

    }
    return SQLiteDatabase.openDatabase(dbFile.getPath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.CREATE_IF_NECESSARY);

}

@Override
public void onCreate(SQLiteDatabase db) {

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}
public Cursor gettitles(SQLiteDatabase db)
{
    db = this.getReadableDatabase();

    Cursor cursor;

    cursor = db.query(true, "Ayervedic", new String[]{"Title"}, null, null, null, null, null, null);
    return cursor;
}

主要活动

public class MainActivity extends AppCompatActivity {

ListView listView;
String title;
SqlLiteDbHelper dbHelper;

SQLiteDatabase sqLiteDatabase;
Cursor cursor;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
   listView= (ListView) findViewById(R.id.listView);
    dbHelper = new SqlLiteDbHelper(this);
    try {
        dbHelper.openDataBase();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    sqLiteDatabase=dbHelper.getReadableDatabase();
    cursor=dbHelper.gettitles(sqLiteDatabase);
    String[] from = new String[] { "Title" };
    int[] to = new int[] {R.id.textView };
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,R.layout.row_title,cursor,from,to);
    adapter.notifyDataSetChanged();
    listView.setAdapter(adapter);
}

Logcat:

Process: com.example.ky.tamil, PID: 6286
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ky.tamil/com.example.aeiltech.tamil.MainActivity}: java.lang.IllegalArgumentException: column '_id' does not exist
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2436)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2498)
        at android.app.ActivityThread.access$900(ActivityThread.java:179)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1324)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:146)
        at android.app.ActivityThread.main(ActivityThread.java:5641)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1288)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1104)
        at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.IllegalArgumentException: column '_id' does not exist

【问题讨论】:

标签: android sqlite simplecursoradapter crash


【解决方案1】:

SimpleCursorAdapter 是 CursorAdapter 的子类。文档states

游标必须包含名为“_id”的列,否则此类将不会 工作。

在您的情况下,您可以将主键 Item No 重命名为 _id

编辑:你还需要在光标中选择这一列,即使它没有映射到视图。

cursor = db.query(true, "Ayervedic", new String[]{"Title", "_id"}, null, null, null, null, null, null);

【讨论】:

  • 怀疑是我没有在我的数据库类@bwt中声明ITEM No
  • 我要更改数据库类还是 SqliteManager??@bwt
  • no such column: _id (code 1): , while compiling: SELECT DISTINCT Title, _id FROM Ayervedic 现在我遇到了这样的错误
  • @karthickYadav 使用投影列,例如:new String[]{"Title", "rowid as _id"}
  • 两者,主键应在create语句中命名为_id,并在创建游标时引用。您可以使用 @pskink 建议的别名,但我认为包含 "Item No" 之类的空格的列名很少是个好主意
【解决方案2】:

您的 SimpleCursor 适配器需要行 _id 才能使用。

CREATE TABLE "Ayervedic" (
   "_id" INT AUTOINCREMENT,
   "Item No" NUMERIC NOT NULL,
   "Title" VARCHAR NOT NULL,
   "Subcategory" VARCHAR NOT NULL,
   "Details" VARCHAR NOT NULL ,
   "Images" VARCHAR NOT NULL ,
   PRIMARY KEY ("_id")
);

【讨论】:

  • 谢谢,但我使用的是外部数据库,我们如何在 Oncreate 中编写 CREATE_TABLE?这可能吗? @马赫
【解决方案3】:

试试这个

Cursor c = db.rawQuery(" SELECT "+ Title + " AS _id from Ayervedic"); 

表示您选择 Title 并使用 AS 将其别名创建到 _id 中,并且您正在从 Ayervedic 表中选择此 id。所以现在您将能够从列名 _​​id 访问此查询的结果,并且为了访问结果,请使用:

c.moveToFirst();    
    while (c.moveToNext())
    {
     System.out.println(c.getString(c.getColumnIndex("_id")); 
    }

【讨论】:

  • thx 但在该字段中,列名有重复,我们如何避免这种情况
  • 是什么意思?我不明白你。哪些列名有重复?
  • 这意味着在我的标题列中我有一个重复时间的字段(即)Apple,orange,grapes,Apple,orange,grapes 如何避免这种重复我只需要一个 Apple,orange,grapes
  • 使用“不同”。从 Ayervedic 中选择不同的 Title 作为 _id
  • " SELECT Title AS _id from Ayervedic" 这一行也显示错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-20
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
相关资源
最近更新 更多