目前,我正在使用数据库处理我的第一个应用程序。 现在我有点困惑。该应用程序是一个原生Android应用程序。我使用SQLite作为数据库系统。
我在处理数据时遇到了一些麻烦。
目前我有一个具有一些属性的人员(firstname
,lastname
,...)。但它也包含ID
。我的DatabaseHandler
有一个名为addPerson(Person p1)
的方法。在该方法中,person
将写入DB。
我正在使用的工作流程: 我的申请包含2页。第一页显示所有人员的列表。第二页是创建具有一些输入字段的人员:
点击create
- 按钮后,我创建了一个新的object of the type Person
。如果成功创建了此人,则调用方法addPerson(Person p1)
。将此人添加到数据库后,我从数据库中获取ID
的{{1}} - 并将其添加到Person
。如果一切正常,页面将被关闭,我来到开始页面,其中列出了所有已创建的Person object
。
更改第一页时,首先清除Person's
并从数据库中读取所有ArrayList<Person> persons
并将其添加到Person's
:ArrayList
。获得所有persons = DBHandler.getAllPersons();
后,我通知Person's
数据已更改。
这个过程非常愚蠢。这是我必须去的正确方法吗?
或者我应该停止使用课程adapater
并仅使用Person
?我在谷歌搜索,但没有找到任何有用的东西帮助我。
答案 0 :(得分:1)
任何一种方式都可以被认为是正确的,更正确的或更不正确的;很大程度上取决于意见。
但是,您需要一个人对象吗?不,没有必要,而是某种偏好。您当然可以在没有 Person 对象的情况下管理数据,而是使用 Cursor 对象,在您的情况下,该对象可以被视为 Person 对象名。
虽然我从未走过这条道路,但你可能有一种组合/中间选项,可能将Cursor类扩展为PersonCursor类,从而将两者结合起来。
关于 ListView
适配器,我个人认为 CursorAdapters
更适合。简而言之,它们可以满足显示多个列的需求,而不需要定制。也就是说,它们允许您提供列的列表(从中获取数据)以及相应视图的列表(它们放置数据的位置)。虽然我可能错了,但我认为没有自定义的ArrayAdapters只能满足单个元素。
例如,要向用户展示可识别的人,您需要姓氏和姓氏。适用于CursorAdpater;提供/开箱即 android.R.layout.simple_list_item_2
的两列可以应对,因为您可以指定从Forename获取数据以及从Surname获取数据并放入分别为android.R.id.text1
和 android.R.id.text2
。
e.g。
mSCA = new SimpleCursorAdapter(this,
android.R.layout.simple_expandable_list_item_2, //<<<< layout
dbhlpr.getAllPeople(), //<<<< Cursor (grabbed directly)
new String[]{
DBHelperPeople.FORENAME_COL, //<<<< Column(a) to show
DBHelperPeople.SURNAME_COL}, //<<<< Column(b) to show
new int[]{
android.R.id.text1, //<<<< view for (a)
android.R.id.text2}, //<<<< view for (b)
0
);
mLV1.setAdapter(mSCA);
对于 ArrayAdapter
,您无法自定义(据我所知(可能是误解)),请指定两个数据项,因此您必须将Forename和Surname结合使用。所以你需要一些方法来结合两个,可能/可能是toString
方法,特定于 Person 类。
e.g。
// ArrayAdapter with Person[] as source
// built within DBHelperPeople getAllPeopleAsPersonArray
mPeople = dbhlpr.getAllPeopleAsPersonArray();
mAAPeeople = new ArrayAdapter<Person>(this,
android.R.layout.simple_expandable_list_item_1,
mPeople
);
mLV3.setAdapter(mAAPeeople);
但是,还需要以下内容: -
public Person[] getAllPeopleAsPersonArray() {
Cursor csr = getAllPeople();
Person[] people = new Person[csr.getCount()];
while (csr.moveToNext()) {
people[csr.getPosition()] = new Person(
csr.getLong(
csr.getColumnIndex(DBHelperPeople.ID_COL)
),
csr.getString(
csr.getColumnIndex(DBHelperPeople.FORENAME_COL)
),
csr.getString(
csr.getColumnIndex(DBHelperPeople.SURNAME_COL)
)
);
}
csr.close();
return people;
}
以及人toString
方法,例如: -
public String toString() {
return mForeName + ", " + mSurname;
}
你可以说只有Cursor方法还需要: -
public Cursor getAllPeople() {
return mDB.query(PEOPLE_TBL,null,null,null,null,null,null);
}
但是,它可能是一种非常常用的DBHelper方法( ooops如此常见getAllPeopleAsPersonArray
使用它)。
当然,一个反驳论点就是拥有一个Person对象,你需要构造函数,也许也是getter和setter。
如果您决定使用 ListView 而不是仅仅查看它,请说单击某个项目并更新或删除某个人。 CursorAdapter
可以很容易处理,因为项目监听器(onItemClickListener
和onItemLongClickListener
)会传递 _id 列的值(请注意,使用的游标必须有一个 _id 列,这是 _id INTEGER PRIMARY KEY
或_id INTEGER PRIMARY KEY AUTOINCREMENT
的理由(前者在大多数情况下效率更高))。
虽然ArrayAdapter同样通过id但它实际上是位置。哪个非常可能与ID无关,SQLite id以1开始,位置从0开始。您可以删除id将保持未使用的行,直到id达到9,223,372,036,854,775,807( PS我不会等到人口达到那个数字。所以位置可能与id相距很远。
然而,您可以(如果您以正确的方式进行,通常在SO上看到未使用正确方法的位置)通过位置从人物对象获取ID。
e.g。
id = mPeople[position].getID(); //
相反,没有任何内容,因为id是为CursorAdapter传递的正确值。
如果成功创建此人,我会调用该方法 addPerson(Person p1)。将人员添加到数据库后,我获得了ID of Person - 从DB - 并将其添加到Person对象。
那是明智的吗? Person对象不会仅保留数据库中的数据。而不是创建新的person对象,将数据添加到数据库,然后更新person对象以供后续使用。为什么不在需要时获得所有人?也许用DBHelper(DatabaseHanlder)的getAllPeopleAsPersonArray
方法创建人物(作为Person数组)( oops我认为我已经放弃了我的忠诚)
我有4个需要存储在DB中的类。 DatabaseHandler 会非常大。
如果您有关于扩展DBHelper的类/表数量的问题。您可以随时根据表格拆分它们。对于有7个表/类(商店,过道,产品,产品用途,规则,购物清单和Appvalues)的购物清单应用程序,我有14个班级;每个的Constants类和方法类。 DBhelper(DatabaseHandler)从表类中引入。