我尝试从SQLite数据库填充ListView,但Log
显示:com.example.apple.bookshelf.Book@3d3844f2
。 Gradle构建没有任何错误或警告。
知道什么是错的吗?
我的数据库设置包含名为id
,title
,author
,collection
和body
的字段。
MainActivity.java
package com.example.apple.bookshelf;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.readystatesoftware.sqliteasset.SQLiteAssetHelper;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ListView authorsListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
authorsListView = (ListView) findViewById(R.id.authors_list_view);
String[] authors = {"Christie, Agatha","Conan Doyle, Arthur","James, M.R."};
DatabaseHelper db = new DatabaseHelper(this);
List bookList = db.getAllBooks();
/*
ArrayAdapter<String> arrayAdapter =
new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, bookList);
authorsListView.setAdapter(arrayAdapter);
*/
Log.i("test", bookList.toString());
}
}
DatabaseHelper.java
package com.example.apple.bookshelf;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.readystatesoftware.sqliteasset.SQLiteAssetHelper;
import java.util.ArrayList;
import java.util.List;
public class DatabaseHelper extends SQLiteAssetHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "books.db";
private static final String TABLE_NAME = "books";
public DatabaseHelper (Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Getting All Contacts
public List<String> getAllBooks() {
List bookList = new ArrayList();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_NAME;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Book book = new Book();
book.setID(Integer.parseInt(cursor.getString(0)));
book.setTitle(cursor.getString(1));
book.setAuthor(cursor.getString(2));
// Adding contact to list
bookList.add(book);
} while (cursor.moveToNext());
}
// return contact list
return bookList;
}
}
Book.java
package com.example.apple.bookshelf;
public class Book {
int id;
String title;
String author;
String collection;
String body;
public Book() {
}
public Book(int id, String title, String author, String collection, String body) {
this.id = id;
this.title = title;
this.author = author;
this.collection = collection;
this.body = body;
}
// getters
public int getID() {
return this.id;
}
public String getTitle() {
return this.title;
}
public String getAuthor() {
return this.author;
}
public String getCollection() {
return this.collection;
}
public String getBody() {
return this.body;
}
// setters
public void setID(int id) {
this.id = id;
}
public void setTitle(String title) {
this.title = title;
}
public void setAuthor(String author) {
this.author = author;
}
public void setCollection(String collection) {
this.collection = collection;
}
public void setBody(String body) {
this.body = body;
}
}
答案 0 :(得分:0)
在getAllBooks
中,您创建并返回Book列表,而不是创建String列表。因此,在MainActivity
中,您实际上是打印Book对象的字符串表示。要解决此问题,您需要将字符串实际放入getAllBooks
的列表中。另外,请始终使用键入的列表(指定菱形中列表元素的类型,例如List<Book>
或List<String>
),以便编译器捕获此类错误。
答案 1 :(得分:0)
简而言之,行bookList.add(book);
将Book对象作为字符串分配给相应的元素,而不是Book的成员/属性,因此@ ....这是对该实例的引用。书。
您可以使用bookList.add(book.addAuthor);
。但是,问题在于使用List,比如通过单击更新列出的书籍会成为问题,因为所有ListView都知道正在显示的文本和列表中的位置。
简而言之,使用字符串数组作为适配器的源会使得返回数据库中保存的原始数据变得困难/有问题。您只能将String或String本身的位置作为参考。该位置不能用于可靠地确定行的rowid,这可以说是访问表的单行的最佳值。位置从0开始,rowid为1; rowid's不能保证增加1,位置会,行可以删除留下空白;根据rowid可能无法订购数据。
您实际上可以将图书列表传递给适配器。尽管ArrayAdapter
使用对象的toString
方法从相应的数组元素中检索文本,但这是一个小问题。为对象提供toString
方法允许您控制显示的内容。但是,在onClickListener中,作为示例,该位置与书籍列表中的书籍相关,然后您可以从中访问其他信息,例如 id 。
因此,如果您要将以下内容添加到Book类中,它将能够显示作者和标题: -
public String toString() {
return this.author + ", " + this.title;
}
您还需要更改getAllBooks
方法以返回一系列图书: -
public Book[] getAllBooks() {
SQLiteDatabase db = this.getWriteableDatabse();
Cursor csr = db.query(TABLE_NAME,null,null,null,null,null,null);
Book[] books = new Book[csr.getCount()];
while (csr.moveToNext) {
books[csr.getPosition] = new Book(
Integer.parseInt(cursor.getString(0)),
cursor.getString(1),
cursor.getString(2),
"","");
}
csr.close;
return books;
}
*注意我建议不使用硬编码偏移,而是使用Cursor的getColumnIndex
方法,例如假设第一列(id)的列名是 _id ,而不是Integer.parseInt(cursor.getString(0))
,您可以使用: -
Integer.parseInt(cursor.getString(csr.getColumnIndex("_id"))
假设ID列是 rowid 的别名,即它已被定义为column_name INTEGER PRIMARY KEY
或column_name INTEGER PRIMARY KEY AUTOINCREMENT
(其中column_name仅表示使用的实际列名称),那么该值可能超过 int 可以容纳的值,因此您应该使用long。你不需要使用Parse和getString来提取值,Cursor有各种get方法,如getInt和getlong。
理想情况下你应该使用: -
cursor.getLong(csr.getColumnIndex("column_name"));
同时更改Book类以使用long id
;
您还需要更改适配器代码: -
DatabaseHelper db = new DatabaseHelper(this);
Book[] booklist = getAllBooks();
ArrayAdapter<Book[]> arrayAdapter =
new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, bookList);
authorsListView.setAdapter(arrayAdapter);
另一种方法是使用 CursorAdapter 。
你可以这样做: -
Cursor csr = db.query(DatabaseHelper.TABLE_NAME,"*,rowid AS _id",null,null,null,null,null);
SimpleCursorAdpater sca = new SimpleCursorAdapter(this,
android.R.layout.simple_expandable_list_item_1,
csr,
new String[]{"title_column"},
new int[]{android.R.id.text1},
0
);
authorsListView.setAdapater(sca);
其中title_column是title列或authour列的名称。
你也可以使用: -
Cursor csr = db.query(DatabaseHelper.TABLE_NAME,"*,rowid AS _id",null,null,null,null,null);
SimpleCursorAdpater sca = new SimpleCursorAdapter(this,
android.R.layout.simple_expandable_list_item_2,
csr,
new String[]{"title_column","author_column"},
new int[]{android.R.id.text1,android.R.id.text2},
0
);
authorsListView.setAdapater(sca);
标题和作者都会出现在列表中。再次使用实际的列名而不是组成的列名。
请注意,上述内容未经测试,因此可能存在奇怪的错误或拼写错误。
我个人会添加一个特定方法来将所有行提取到DatabaseHelper类,例如getAllBooks可能是: -
public Cursor getAllBooks() {
return this.getWriteableDatabase().query(TABLE_NAME,"*,rowid AS _id",null,null,null,null,null);
}
请注意! "*, rowid AS _id"
,假设您的 id 列未命名为 _id 。如果 id 列名为 _id ,则query
方法的第二个参数可以为null。 CursorAdapter要求有一个名为 _id 的列。然后将其传递给onItemClickListener
和onItemLongClickListener
。