我创建了一个带有SQLite数据库和ListView的应用程序,我想用数据库填充它。为此,我编写了一个名为HomeListAdapter的适配器类。这个类需要4个字符串数组作为输入,这就是我的问题所在。起初,我只是使用随机字符串数组来填充ListView,方法是自己输入,例如:
String[] homelist_name_short = {
"Flower", "Bush", "Tree"};
String[] homelist_name_long = {
"Red rose", "Berry bush", "Oak"};
String[] homelist_date = {
"20-9-2017", "11-10-2017", "12-10-2017"};
String[] homelist_price = {
"€1.50", "€2.48", "€0.68"};
现在我希望将其自动放入listview,为此我已经编写了可以在下面看到的代码..
我创建了一个名为Home的类:
public class Home {
private String mShortHomeName;
private String mLongHomeName;
private String mHomeDate;
private String mHomePrice;
public Home(String ShortName, String LongName, String Date, String Price) {
this.mShortHomeName = ShortName;
this.mLongHomeName = LongName;
this.mHomeDate = Date;
this.mHomePrice = Price;
}
public String getShortName() {
return this.mShortHomeName;
}
public String getLongName() {
return this.mLongHomeName;
}
public String getDate() {
return this.mHomeDate;
}
public String getPrice() {
return this.mHomePrice;
}
}
在我的DatabaseHelper中添加了以下内容:
public Cursor getAllHomesAsCursor() {
SQLiteDatabase db = this.getWritableDatabase();
String[] columns = {"rowid as _id","*"};
return db.query(TABLE_NAME,columns,null,null,null,null,null);
}
包含我的listview的活动的以下内容:
DatabaseHelper db = new DatabaseHelper(getActivity());
Cursor csr = db.getAllHomesAsCursor();
HLAdapter adapter = new HLAdapter(getActivity(), csr);
listView.setAdapter(adapter);
HLAdapter如下所示:
public class HLAdapter extends CursorAdapter {
public HLAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
@Override
public View newView(Context context, Cursor csr, ViewGroup parent) {
return LayoutInflater.from(context).inflate(
R.layout.homelist_listview_layout,
parent,
false
);
}
@Override
public void bindView(View view, Context context, Cursor csr) {
TextView sname = (TextView) view.findViewById(R.id.homelist_name_short);
TextView lname = (TextView) view.findViewById(R.id.homelist_name_long);
TextView date = (TextView) view.findViewById(R.id.homelist_date);
TextView price = (TextView) view.findViewById(R.id.homelist_price);
sname.setText(csr.getString(csr.getColumnIndex("name_short")));
lname.setText(csr.getString(csr.getColumnIndex("name_long")));
date.setText(csr.getString(csr.getColumnIndex("date")));
price.setText(csr.getString(csr.getColumnIndex("price")));
}
}
我的DatabaseHelper类如下所示:
public class DatabaseHelper extends SQLiteOpenHelper{
public static final String DATABASE_NAME = "Main.db";
public static final String TABLE_NAME = "current_table";
public static final String COL_1 = "name_short";
public static final String COL_2 = "name_long";
public static final String COL_3 = "date";
public static final String COL_4 = "price";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + TABLE_NAME + " (name_short TEXT,name_long TEXT, due_date TEXT, price TEXT) ");
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
public Cursor getAllHomesAsCursor() {
SQLiteDatabase db = this.getWritableDatabase();
String[] columns = {"rowid as _id","*"};
return db.query(TABLE_NAME,columns,null,null,null,null,null);
}
public boolean insertData(String name_short, String name_long, String due_date, String price) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_1,name_short);
contentValues.put(COL_2,name_long);
contentValues.put(COL_3,due_date);
contentValues.put(COL_4,price);
long result = db.insert(TABLE_NAME,null,contentValues);
if(result == -1)
return false;
else
return true;
}
public void deleteAllData() {
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("DELETE FROM " + TABLE_NAME);
}
public Cursor getAllData() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery("SELECT * FROM " + TABLE_NAME ,null);
return res;
}
public Cursor getSpecifiedColumnData(String column) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("SELECT column FROM " + TABLE_NAME,null);
return res;
}
}
我认为我的代码应该运行正常,但是当我运行应用程序时。它会立即关闭。你能告诉我这是什么问题吗?
答案 0 :(得分:0)
我认为问题在于您需要将4个String数组传递给适配器,因此,如上所述,您需要为每种类型提供唯一的getAllData
等效项。
然而,考虑到房屋名称较短,名称,日期和价格较长,更好的方法是将所有这些属性视为对象,从而创建一个类。然后,您可以创建一个List not of String对象,但作为House对象列表,您可以一次性获取所有这些对象等。
所以(P.S.为了我的理智,我将SO4522191合并到下面,所以我可以保留一些代码跟踪): -
在这种情况下,我称之为 SO45422191Home ,代码可以是: -
public class SO45422191Home {
private String mShortHomeName;
private String mLongHomeName;
private String mHomeDate;
private String mHomePrice;
public SO45422191Home(String ShortName, String LongName, String Date, String Price) {
this.mShortHomeName = ShortName;
this.mLongHomeName = LongName;
this.mHomeDate = Date;
this.mHomePrice = Price;
}
public String getShortName() {
return this.mShortHomeName;
}
public String getLongName() {
return this.mLongHomeName;
}
public String getDate() {
return this.mHomeDate;
}
public String getPrice() {
return this.mHomePrice;
}
}
解释
使用上面我们可以在其他地方的代码中创建一个SO45422191Home对象,例如在你的活动中,通过使用某些东西 比如
SO45422191Home Myhome = new SO45422191Home("Flower","Red Rose","20-9-2017","1.50");
。使用MyHome对象,您可以提取属性,例如
MyHome.getPrice()
将返回值为 1.50 的字符串。 与其他属性相似。您可以创建一个对象数组,例如
设置数组的第一个元素SO45422191Home[] homes = new SO45422191Home[3];
将创建一个3(空)SO45422191Home的数组 对象。我们可以使用homes[0] = new SO45422191Home("Bush","Cherry","11-10-2017","2.48");
这里有一些代码: -
public List<SO45422191Home> getAllHomes() {
List<SO45422191Home> rv = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr = db.query(HOMETABLE,null,null,null,null,null,null);
while (csr.moveToNext()) {
SO45422191Home h = new SO45422191Home(
csr.getString(csr.getColumnIndex(SHORTHOMENAME)),
csr.getString(csr.getColumnIndex(LONGHOMENAME)),
csr.getString(csr.getColumnIndex(HOMEDATE)),
csr.getString(csr.getColumnIndex(HOMEPRICE))
);
rv.add(h);
}
csr.close();
return rv;
}
说明您使用了List并在列表中添加了元素,List类似但是对于SO45422191Home对象而不是
比String对象。
使用
SQLiteDatabase db = this.getWritableDatabase();
打开数据库(如果尚未打开)。将所有行提取到游标中。
一次遍历每行的光标。
对于每一行,通过从光标获取相应数据来创建 SO45422191Home 对象
(请注意,使用了
csr.getColumnIndex(columnname)
而不是对列的索引/偏移进行硬编码,这样做可以减少 错误的可能性以及减少的开销应该是变化的 应用的)。新对象已添加到列表中。
显然必须调整列名,您可能还想在返回前添加
db.close()
。
这是列表使用的示例适配器(请注意, R.layout.homeentry
是ListView中每个条目使用的布局),布局如下所示
public class AdapterHomeList2 extends ArrayAdapter {
List<SO45422191Home> homes;
LayoutInflater lInflater;
public AdapterHomeList2(Context context, List<SO45422191Home> homes) {
super(context,R.layout.homeentry, homes);
lInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.homes = homes;
}
@Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.homeentry, parent, false);
}
TextView sname = (TextView) view.findViewById(R.id.shortname);
TextView lname = (TextView) view.findViewById(R.id.longname);
TextView date = (TextView) view.findViewById(R.id.date);
TextView price = (TextView) view.findViewById(R.id.price);
sname.setText(homes.get(position).getShortName());
lname.setText(homes.get(position).getLongName());
date.setText(homes.get(position).getDate());
price.setText(homes.get(position).getPrice());
return view;
}
}
这是 ArrayList 的代码: -
public class AdapterHomeList3 extends ArrayAdapter {
ArrayList<SO45422191Home> homes;
LayoutInflater lInflater;
public AdapterHomeList3(Context context, ArrayList<SO45422191Home> homes) {
super(context,R.layout.homeentry, homes);
lInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.homes = homes;
}
@Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.homeentry, parent, false);
}
TextView sname = (TextView) view.findViewById(R.id.shortname);
TextView lname = (TextView) view.findViewById(R.id.longname);
TextView date = (TextView) view.findViewById(R.id.date);
TextView price = (TextView) view.findViewById(R.id.price);
sname.setText(homes.get(position).getShortName());
lname.setText(homes.get(position).getLongName());
date.setText(homes.get(position).getDate());
price.setText(homes.get(position).getPrice());
return view;
}
}
public Cursor getAllHomesAsCursor() {
SQLiteDatabase db = this.getWritableDatabase();
String[] columns = {"rowid as _id","*"};
return db.query(HOMETABLE,columns,null,null,null,null,null);
}
请注意!代替所有列,即编码null作为第二参数 要查询&#39; (没有得到隐藏的rowid列(假设 没有ROWID还没有使用过)),会得到rowid(unqiue) 行标识符)并将此 AS _id命名为套件游标适配器 因此
"rowid as _id"
,以下*
作为第二个元素 columns数组表示所有行(将null指定为第二个参数 结果为SELECT * .....
)。否则它非常简单。注意您不能关闭数据库, 否则你无法访问光标。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/shortname"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/longname"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/date"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/price"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
</LinearLayout>
public class AdapterHomeList extends CursorAdapter {
public AdapterHomeList(Context context, Cursor cursor) {
super(context, cursor,0);
}
@Override
public View newView(Context context, Cursor csr, ViewGroup parent) {
return LayoutInflater.from(context).inflate(
R.layout.homeentry, //<< layout for each list item
parent,
false
);
}
@Override
public void bindView(View view, Context context, Cursor csr) {
TextView sname = (TextView) view.findViewById(R.id.shortname);
TextView lname = (TextView) view.findViewById(R.id.longname);
TextView date = (TextView) view.findViewById(R.id.date);
TextView price = (TextView) view.findViewById(R.id.price);
sname.setText(csr.getString(csr.getColumnIndex(SO45422191.SHORTHOMENAME)));
lname.setText(csr.getString(csr.getColumnIndex(SO45422191.LONGHOMENAME)));
date.setText(csr.getString(csr.getColumnIndex(SO45422191.HOMEDATE)));
price.setText(csr.getString(csr.getColumnIndex(SO45422191.HOMEPRICE)));
}
}
请注意!
R.layout.homeentry
是列表条目的布局 并且id来自此。
e.g: -
Cursor csr = dbhlp.getAllHomesAsCursor();
AdapterHomeList ahl = new AdapterHomeList(this,csr);
ListView hl = (ListView) this.findViewById(R.id.homelist);
hl.setAdapter(ahl);
结果: -
int getColumnIndex (String columnName)
返回给定列名的从零开始的索引,如果是,则返回-1 专栏不存在。如果您希望列存在使用 相反,getColumnIndexOrThrow(String)会使错误更多 清楚。
使用getColumnIndex而不是指定索引,无需手动确定列偏移。
例如,有一个名为项目的表格,其中包含3列,名称为名称,日期和价格< / strong>: -
使用相当于SELECT * FROM items
的查询,查询将返回包含3列的游标,名称,日期和价格< /强>
要从光标中提取日期,您可以编码cursor.getString(1);
但是,如果您要根据SELECT date, price, name FROM items
进行查询,则偏移量为: -
在这种情况下,您必须编码cursor.getString(0);
以提取日期。
可能很容易无意中编码错误的偏移量,尤其是在使用较大的表或连接表或引入生成的列时。
在两种情况下都可以使用cursor.getString(cursor.getColumnIndex("date"));
,因为它会在第一种情况下返回1,在第二种情况下返回0。
以上,作为示例,sname.setText(csr.getString(csr.getColumnIndex(SO45422191.SHORTHOMENAME)));
已被编码。
Home.SHORTHOMENAME
是数据库助手中定义的类变量(即 SO45422191
是DatabaseHelper类, SHORTHOMENAME
是类变量),相当于相应列的列名,可以从数据库助手代码提取中看到: -
public class SO45422191 extends SQLiteOpenHelper {
public static final String DBNAME = "SO45422191";
public static final String HOMETABLE = "homes";
public static final String SHORTHOMENAME = "shorthomename";
public static final String LONGHOMENAME = "longhomename";
public static final String HOMEDATE = "homedate";
public static final String HOMEPRICE = "homeprice";
// constructor
public SO45422191(Context context) {
super(context, DBNAME , null , 1);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("create table " + HOMETABLE +
"(" +
SHORTHOMENAME + " TEXT, " +
LONGHOMENAME + " TEXT, " +
HOMEDATE + " TEXT, " +
HOMEPRICE + ")");