如何从SQLite数据库中检索数据并在ListView for Java Android应用程序上显示

时间:2018-01-30 01:09:28

标签: java android sqlite listview

所以我在另一个页面上创建了一个数据库,它正在运行。现在我试图从SQLite数据库中检索数据并在Android应用程序的ListView上显示。

我为它编写了一个代码,但显然每次我尝试查看都会崩溃。请指教

我想以这样的方式运行 注册 - >登录 - >查看空列表视图 - >添加记录 - >查看包含已添加记录的列表视图

更新了崩溃日志:

01-29 20:42:19.971: E/AndroidRuntime(6003): FATAL EXCEPTION: main
01-29 20:42:19.971: E/AndroidRuntime(6003): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.manandhowproject/mdad.project.Medrecord}: java.lang.IllegalArgumentException: column '_id' does not exist
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.app.ActivityThread.access$600(ActivityThread.java:141)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.os.Looper.loop(Looper.java:137)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.app.ActivityThread.main(ActivityThread.java:5103)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at java.lang.reflect.Method.invokeNative(Native Method)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at java.lang.reflect.Method.invoke(Method.java:525)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at dalvik.system.NativeStart.main(Native Method)
01-29 20:42:19.971: E/AndroidRuntime(6003): Caused by: java.lang.IllegalArgumentException: column '_id' does not exist
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:303)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.widget.CursorAdapter.init(CursorAdapter.java:168)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.widget.CursorAdapter.<init>(CursorAdapter.java:145)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.widget.ResourceCursorAdapter.<init>(ResourceCursorAdapter.java:91)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.widget.SimpleCursorAdapter.<init>(SimpleCursorAdapter.java:104)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at mdad.project.Medrecord.onCreate(Medrecord.java:34)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.app.Activity.performCreate(Activity.java:5133)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
01-29 20:42:19.971: E/AndroidRuntime(6003):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
01-29 20:42:19.971: E/AndroidRuntime(6003):     ... 11 more

MedRecords.java

package mdad.project;

import com.example.manandhowproject.R;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

public class Medrecord extends Activity {
    SQLiteDatabase db;
    ListView lvMedRec;
    SimpleCursorAdapter adapter;
    Cursor cursor;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.medrecord);
    createDatabase();
    Cursor c = null;
    c = db.rawQuery("select * from MedRecords",null);String[] from = new String[]{"Bodytemp","HeartRate","BMI"};
    int[] to = new int[]{R.id.etBodyTemp, R.id.etHeartRate, R.id.etBMI};
    adapter = new SimpleCursorAdapter(this,R.layout.medrecord,c,from,to,0);

    ListView lvMedRec = (ListView)findViewById(R.id.lvMedRec);
    lvMedRec.setAdapter(adapter);


    Button button = (Button)findViewById(R.id.btnAdd);
    button.setOnClickListener(new OnClickListener(){
        public void onClick (View V){

        Intent msg5 = new Intent(Medrecord.this, Addorupdate.class);
        startActivity(msg5);
        }
    });

    Button button2 = (Button)findViewById(R.id.btnUpdate);
    button2.setOnClickListener(new OnClickListener(){
        public void onClick (View V){

        Intent msg6 = new Intent(Medrecord.this, Addorupdate.class);
        startActivity(msg6);
        }
    });

    Button button3 = (Button)findViewById(R.id.btnSignOut);
    button3.setOnClickListener(new OnClickListener(){
        public void onClick (View V){
        Toast.makeText(getApplicationContext(), "Log Out Success ! ", Toast.LENGTH_LONG).show();
        Intent msg7 = new Intent(Medrecord.this, Login.class);
        startActivity(msg7);
        }
    });
}

 protected void createDatabase(){
        db = openOrCreateDatabase("MedRec",Context.MODE_PRIVATE,null);
        db.execSQL("CREATE TABLE IF NOT EXISTS MedRecords(recld integer PRIMARY KEY autoincrement, Bodytemp text, HeartRate text, BMI text;");

    }

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.fourth, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

}

3 个答案:

答案 0 :(得分:0)

是的,看起来是SQL语法错误:

Caused by: java.lang.IllegalArgumentException: column '_id' does not exist

它说你没有'_id'列,它可能来自你创建SimpleCursorAdapter的地方:

adapter = new SimpleCursorAdapter(this,R.layout.medrecord,c,from,to,0);

请参阅此问题:Simple Cursor Adapter problem

修复方法是将'_id'列添加到光标中。但是你已经在光标中添加了所有内容('*'),所以它应该在那里吗?

除非您在表中创建了一个名为'recld'的显式主键,这意味着您的表将没有内置的'_id'列。

无论如何,使用'_id'列作为主键。

protected void createDatabase(){
    db = openOrCreateDatabase("MedRec",Context.MODE_PRIVATE,null);
    db.execSQL("CREATE TABLE IF NOT EXISTS MedRecords(_id INTEGER PRIMARY KEY autoincrement, Bodytemp text, HeartRate text, BMI text);");
}  

答案 1 :(得分:0)

您忘了关闭查询。

db.execSQL("CREATE TABLE IF NOT EXISTS MedRecords(recld integer PRIMARY KEY autoincrement, Bodytemp text, HeartRate text, BMI text);");

为什么你要使用自动增量?

更新:

此外,您正在尝试使用需要名为“_id”的列的游标。编辑表创建语句。

db.execSQL("CREATE TABLE IF NOT EXISTS MedRecords(_id INTEGER PRIMARY KEY autoincrement, Bodytemp text, HeartRate text, BMI text);");

答案 2 :(得分:0)

游标适配器要求游标有一个名为 _id 的列(您遇到的错误),这应该是所有表的唯一标识符,除非{{ 1}}短语用于表格的创建,有。

此唯一标识符是一个名为 rowid 的特殊常用隐藏列。编码WITHOUT ROWID?? INTEGER PRIMARY KEY为名为??的rowid列创建别名(其中??是有效的列名)。

因此,在提取光标时,您可以使用 ??INTEGER PRIMARAY KEY AUTOINCREMENT 关键字来使用现有表格。例如改变: -

AS

<强> c = db.rawQuery("select * from MedRecords",null);String[] from = new String[]{"Bodytemp","HeartRate","BMI"};

会产生一个包含 _id 列的光标以及 MedRecords 表中的所有其他列。

或者,由于 recld 是您可以使用的rowid的别名: -

<强> c = db.rawQuery("select rowid AS _id,* from MedRecords",null);String[] from = new String[]{"Bodytemp","HeartRate","BMI"};

同样,您将拥有一个_id列以及所有其他列,包括Cursor中的 recld 列。

表创建SQL似乎也存在问题,因为缺少尾随的右括号,而不是: -

c = db.rawQuery("select recld AS _id,* from MedRecords",null);String[] from = new String[]{"Bodytemp","HeartRate","BMI"};

你应该: -

db.execSQL("CREATE TABLE IF NOT EXISTS MedRecords(recld integer PRIMARY KEY autoincrement, Bodytemp text, HeartRate text, BMI text;");

但是,如果表格已经存在,则更改上述内容不会更改表格(似乎是这种情况)。如果数据可能丢失,那么在运行根据上述更改之前,您应删除应用程序的数据或卸载应用程序。

如果您需要当前拥有的数据,那么请仔细阅读ALTER TABLE,尤其是标题为 制作其他各种表架构更改 的部分

备注

  • 很少需要编码db.execSQL("CREATE TABLE IF NOT EXISTS MedRecords(recld integer PRIMARY KEY autoincrement, Bodytemp text, HeartRate text, BMI text);"); ,它不会将列更改为自动生成唯一ID(rowid)。编码AUTOINCREMENT就是这么做的。 INTEGER PRIMARY KEY做的是保证唯一id(rowid)将大于上一次生成的id。它通过使用另一个名为sqlite_sequence的表来以额外的成本存储最后使用的唯一标识符。 SQLite文档声明: -
  

AUTOINCREMENT关键字会产生额外的CPU,内存,磁盘空间和磁盘I / O开销,如果不是严格需要,应该避免使用。通常不需要它。

更多信息