无法使用 sqlite 数据库中的数据填充列表视图
Cant populate list view with data from sqlite database
我正在尝试学习 Android 开发。作为一个学习项目,我正在创建一个 'To Do' 应用程序。
我正在尝试用我的 table 中的数据填充列表,这是我目前所拥有的:
ListCursorAdapter.java
package com.ryansmurphy.listado;
import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* Created by ryanmurphy on 24/02/15.
*/
public class ListCursorAdapter extends CursorAdapter {
public ListCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.item_todo, parent, false);
}
public void bindView(View view, Context context, Cursor cursor) {
// Find fields to populate in inflated template
TextView todo = (TextView) view.findViewById(R.id.todoText);
// Extract properties from cursor
String todoTextDB = cursor.getString(cursor.getColumnIndexOrThrow("todo"));
// Populate fields with extracted properties
todo.setText(todoTextDB);
}
}
这里有两个错误:
- 在
extends cursor
。我收到错误 Cannot resolve symbol
.
- 在
super(context, cursor, 0);
。我收到错误 Object() in Object cannot be applied to
.
DatabaseHelper.java
package com.ryansmurphy.listado;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by ryanmurphy on 23/02/15.
*/
public class DatabaseHelper extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "listado";
// Table Name
private static final String TABLE_TODO = "todos";
// Column names
private static final String KEY_ID = "id";
private static final String KEY_TODO = "todo";
private static final String KEY_STATUS = "status";
private static final String KEY_CREATED_AT = "created_at";
// Table Create Statements
// Todo table create statement
private static final String CREATE_TABLE_TODO = "CREATE TABLE "
+ TABLE_TODO + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_TODO
+ " TEXT," + KEY_STATUS + " INTEGER," + KEY_CREATED_AT
+ " DATETIME" + ")";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// creating required table
db.execSQL(CREATE_TABLE_TODO);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// on upgrade drop older tables
db.execSQL("DROP TABLE IF EXISTS " + TABLE_TODO);
// create new tables
onCreate(db);
}
public void addRecord()
{
SQLiteDatabase database = getWritableDatabase();
ContentValues values = new ContentValues();
values.put("todo", "todo example");
values.put("status", "not completed");
database.insert("todos", null, values);
database.close();
}
public Cursor getAll()
{
SQLiteDatabase database = getReadableDatabase();
Cursor cursor = database.rawQuery("select * from todos",null);
return cursor;
}
}
现在我的列表视图单行 xml:
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:id="@+id/todoText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24dp"
android:padding="6dp" />
</LinearLayout>
ActivityMain.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView android:text="To Do List" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/title" />
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/listview"
android:layout_below="@id/title"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="42dp" />
</RelativeLayout>
MainActivity.Java
package com.ryansmurphy.listado;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView lvItems = (ListView) findViewById(R.id.listview);
// Setup cursor adapter using cursor from last step
DatabaseHelper db = new DatabaseHelper();
Cursor allRows = db.getAll();
ListCursorAdapter todoAdapter = new ListCursorAdapter(this, allRows);
//Attach cursor adapter to the ListView
lvItems.setAdapter(todoAdapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, 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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
if(id == R.id.addItem)
{
addItem();
}
return super.onOptionsItemSelected(item);
}
public void addItem()
{
Intent addItemIntent= new Intent(MainActivity.this, AddItem.class);
startActivity(addItemIntent);
}
}
这里有两个错误:
- 在
DatabaseHelper db = new DatabaseHelper();
。我收到错误 DatabaseHelper(Context) in DatabaseHelper cannot be applied
.
- 在
lvItems.setAdapter(todoAdapter);
。我收到错误 setAdapter(android.widget.ListAdapter) in ListView cannot be applied
.
以上是我通过谷歌搜索、尝试和尝试得到的。我从来不知道我从一开始就在做什么,但我正在慢慢地接受这个,并且想知道你们是否可以在走到这一步之后帮助我。谢谢
我将您的代码复制到一个新项目并进行了一些改动以使其正常运行。我完全剥离了一些区域 - 例如,getAll()
方法,我用 MainActivity
中的查询替换了它。 Here is what the application looks like on first loading, and here 是点击 "add" 几次后的样子。
就其价值而言,我认为有更简单的方法可以实现这一点 - 例如,通过使用 SimpleCursorAdapter
,这将不需要创建您自己的自定义 Adapter
class,并让您的 MainActivity
扩展 ListActivity
或 ListFragment
。但是,我一直坚持使用你的方法。
除了删除 getAll()
方法外,我还对 DatabaseHelper 进行了以下小改动:
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE todos (_id INTEGER PRIMARY KEY, todo TEXT, status INTEGER, created_at INTEGER);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.e(getClass().getSimpleName(), "onUpgrade: this is not required.");
}
我更改了冗长的串联 String CEATE_TABLE_TODO
,因为我觉得它更容易阅读。我还更改了列,以便它们包含文本和数字的混合。我还将 onUpgrade()
方法换成了一条简单的错误消息,因为我们不应该在测试期间使用 onUpgrade()
,因为只有在升级已经发布的应用程序时才需要它。
我对 ListCursorAdapter
做了一些小改动,以便信息显示一些有用的信息 - 在本例中,String
位于 cursor.getString(1)
(第一列)。
public class ListCursorAdapter extends CursorAdapter {
LayoutInflater inflater;
public ListCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return inflater.inflate(R.layout.list_item, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView todo = (TextView) view.findViewById(R.id.todoText);
String todoTextDB = cursor.getString(1);
todo.setText(todoTextDB);
}
}
在MainActivity
中,你的DatabaseHelper
需要一个context
参数,我用this
实现了。 (如果你回头看看 DatabaseHelper
:
中的构造函数,你会看到这一点
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
除此之外,我所做的唯一重大更改是将 DatabaseHelper
query
移动到 MainActivity
中,我将其放入名为 runCursor()
的方法中,这样我们就可以每次我们使用 addItem()
添加新项目时更新我们的 ListView
。
public class MainActivity extends ActionBarActivity {
DatabaseHelper db;
ListView lv;
ListCursorAdapter adapter;
Cursor allRows;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = new DatabaseHelper(this);
lv = (ListView) findViewById(R.id.list);
adapter = new ListCursorAdapter(this, runCursor());
lv.setAdapter(adapter);
}
@Override
public void onDestroy(){
if (allRows != null) {
allRows.close();
}
adapter.getCursor().close();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
if(id == R.id.addItem)
{
addItem();
}
return super.onOptionsItemSelected(item);
}
public void addItem()
{
db.addRecord();
adapter.changeCursor(runCursor());
}
Cursor runCursor() {
Cursor allRows = null;
allRows = db.getReadableDatabase().query(DatabaseHelper.TABLE_TODO,
new String[] {DatabaseHelper.KEY_ID, DatabaseHelper.KEY_TODO},
null, null, null, null, null);
return allRows;
}
}
我还应该提到,我通过重写 onDestroy() 显式关闭了所有游标对象,因为它们很容易发生内存泄漏。我还没有在这里做的最后一句话是,最好将任何游标 query() 移动到后台线程,如 AsyncTask
。我推荐 Android Developer page 上有更多关于 Cursor
的信息!希望这有用!
我正在尝试学习 Android 开发。作为一个学习项目,我正在创建一个 'To Do' 应用程序。
我正在尝试用我的 table 中的数据填充列表,这是我目前所拥有的:
ListCursorAdapter.java
package com.ryansmurphy.listado;
import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* Created by ryanmurphy on 24/02/15.
*/
public class ListCursorAdapter extends CursorAdapter {
public ListCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.item_todo, parent, false);
}
public void bindView(View view, Context context, Cursor cursor) {
// Find fields to populate in inflated template
TextView todo = (TextView) view.findViewById(R.id.todoText);
// Extract properties from cursor
String todoTextDB = cursor.getString(cursor.getColumnIndexOrThrow("todo"));
// Populate fields with extracted properties
todo.setText(todoTextDB);
}
}
这里有两个错误:
- 在
extends cursor
。我收到错误Cannot resolve symbol
. - 在
super(context, cursor, 0);
。我收到错误Object() in Object cannot be applied to
.
DatabaseHelper.java
package com.ryansmurphy.listado;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by ryanmurphy on 23/02/15.
*/
public class DatabaseHelper extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "listado";
// Table Name
private static final String TABLE_TODO = "todos";
// Column names
private static final String KEY_ID = "id";
private static final String KEY_TODO = "todo";
private static final String KEY_STATUS = "status";
private static final String KEY_CREATED_AT = "created_at";
// Table Create Statements
// Todo table create statement
private static final String CREATE_TABLE_TODO = "CREATE TABLE "
+ TABLE_TODO + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_TODO
+ " TEXT," + KEY_STATUS + " INTEGER," + KEY_CREATED_AT
+ " DATETIME" + ")";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// creating required table
db.execSQL(CREATE_TABLE_TODO);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// on upgrade drop older tables
db.execSQL("DROP TABLE IF EXISTS " + TABLE_TODO);
// create new tables
onCreate(db);
}
public void addRecord()
{
SQLiteDatabase database = getWritableDatabase();
ContentValues values = new ContentValues();
values.put("todo", "todo example");
values.put("status", "not completed");
database.insert("todos", null, values);
database.close();
}
public Cursor getAll()
{
SQLiteDatabase database = getReadableDatabase();
Cursor cursor = database.rawQuery("select * from todos",null);
return cursor;
}
}
现在我的列表视图单行 xml: list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:id="@+id/todoText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24dp"
android:padding="6dp" />
</LinearLayout>
ActivityMain.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView android:text="To Do List" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/title" />
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/listview"
android:layout_below="@id/title"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="42dp" />
</RelativeLayout>
MainActivity.Java
package com.ryansmurphy.listado;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView lvItems = (ListView) findViewById(R.id.listview);
// Setup cursor adapter using cursor from last step
DatabaseHelper db = new DatabaseHelper();
Cursor allRows = db.getAll();
ListCursorAdapter todoAdapter = new ListCursorAdapter(this, allRows);
//Attach cursor adapter to the ListView
lvItems.setAdapter(todoAdapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, 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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
if(id == R.id.addItem)
{
addItem();
}
return super.onOptionsItemSelected(item);
}
public void addItem()
{
Intent addItemIntent= new Intent(MainActivity.this, AddItem.class);
startActivity(addItemIntent);
}
}
这里有两个错误:
- 在
DatabaseHelper db = new DatabaseHelper();
。我收到错误DatabaseHelper(Context) in DatabaseHelper cannot be applied
. - 在
lvItems.setAdapter(todoAdapter);
。我收到错误setAdapter(android.widget.ListAdapter) in ListView cannot be applied
.
以上是我通过谷歌搜索、尝试和尝试得到的。我从来不知道我从一开始就在做什么,但我正在慢慢地接受这个,并且想知道你们是否可以在走到这一步之后帮助我。谢谢
我将您的代码复制到一个新项目并进行了一些改动以使其正常运行。我完全剥离了一些区域 - 例如,getAll()
方法,我用 MainActivity
中的查询替换了它。 Here is what the application looks like on first loading, and here 是点击 "add" 几次后的样子。
就其价值而言,我认为有更简单的方法可以实现这一点 - 例如,通过使用 SimpleCursorAdapter
,这将不需要创建您自己的自定义 Adapter
class,并让您的 MainActivity
扩展 ListActivity
或 ListFragment
。但是,我一直坚持使用你的方法。
除了删除 getAll()
方法外,我还对 DatabaseHelper 进行了以下小改动:
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE todos (_id INTEGER PRIMARY KEY, todo TEXT, status INTEGER, created_at INTEGER);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.e(getClass().getSimpleName(), "onUpgrade: this is not required.");
}
我更改了冗长的串联 String CEATE_TABLE_TODO
,因为我觉得它更容易阅读。我还更改了列,以便它们包含文本和数字的混合。我还将 onUpgrade()
方法换成了一条简单的错误消息,因为我们不应该在测试期间使用 onUpgrade()
,因为只有在升级已经发布的应用程序时才需要它。
我对 ListCursorAdapter
做了一些小改动,以便信息显示一些有用的信息 - 在本例中,String
位于 cursor.getString(1)
(第一列)。
public class ListCursorAdapter extends CursorAdapter {
LayoutInflater inflater;
public ListCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return inflater.inflate(R.layout.list_item, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView todo = (TextView) view.findViewById(R.id.todoText);
String todoTextDB = cursor.getString(1);
todo.setText(todoTextDB);
}
}
在MainActivity
中,你的DatabaseHelper
需要一个context
参数,我用this
实现了。 (如果你回头看看 DatabaseHelper
:
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
除此之外,我所做的唯一重大更改是将 DatabaseHelper
query
移动到 MainActivity
中,我将其放入名为 runCursor()
的方法中,这样我们就可以每次我们使用 addItem()
添加新项目时更新我们的 ListView
。
public class MainActivity extends ActionBarActivity {
DatabaseHelper db;
ListView lv;
ListCursorAdapter adapter;
Cursor allRows;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = new DatabaseHelper(this);
lv = (ListView) findViewById(R.id.list);
adapter = new ListCursorAdapter(this, runCursor());
lv.setAdapter(adapter);
}
@Override
public void onDestroy(){
if (allRows != null) {
allRows.close();
}
adapter.getCursor().close();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
if(id == R.id.addItem)
{
addItem();
}
return super.onOptionsItemSelected(item);
}
public void addItem()
{
db.addRecord();
adapter.changeCursor(runCursor());
}
Cursor runCursor() {
Cursor allRows = null;
allRows = db.getReadableDatabase().query(DatabaseHelper.TABLE_TODO,
new String[] {DatabaseHelper.KEY_ID, DatabaseHelper.KEY_TODO},
null, null, null, null, null);
return allRows;
}
}
我还应该提到,我通过重写 onDestroy() 显式关闭了所有游标对象,因为它们很容易发生内存泄漏。我还没有在这里做的最后一句话是,最好将任何游标 query() 移动到后台线程,如 AsyncTask
。我推荐 Android Developer page 上有更多关于 Cursor
的信息!希望这有用!