android - 如何创建一个 SQLite 数据库来存储用户键入的输入,与列表视图无关?
问题描述
我不知道如何创建一个数据库来存储我的用户信息。我对如何创建数据库有一个粗略的想法,但这仅适用于列表视图中的项目。我想存储我的用户信息,以便我可以随时编辑信息。但是每当我输入值并设法获取我的卡路里时,一旦我退出应用程序,我就必须再次重新输入所有信息。
这是我的布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
tools:context=".Calculator"
android:background="@android:color/holo_orange_light">
<TextView
android:id="@+id/Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name:"
android:textAppearance="@style/TextAppearance.AppCompat"
android:textSize="15sp"
android:layout_above="@+id/Age"
android:layout_alignEnd="@+id/Age"
android:layout_alignTop="@+id/food"
android:layout_alignParentStart="true"
/>
<TextView
android:id="@+id/Weight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/weight"
android:layout_alignEnd="@+id/Height"
android:layout_alignParentStart="true"
android:layout_below="@+id/Height"
android:text="Weight: (kg)"
android:textAppearance="@style/TextAppearance.AppCompat"
android:textSize="15sp" />
<TextView
android:id="@+id/Height"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/height"
android:layout_alignParentStart="true"
android:layout_below="@+id/age"
android:text="Height: (cm)"
android:textAppearance="@style/TextAppearance.AppCompat"
android:textSize="15sp" />
<TextView
android:id="@+id/Age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Age:"
android:textAppearance="@style/TextAppearance.AppCompat"
android:textSize="15sp"
android:layout_above="@+id/Height"
android:layout_below="@+id/food"
android:layout_alignParentStart="true"
android:layout_alignEnd="@+id/Height" />
<TextView
android:id="@+id/Gender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Gender: "
android:textAppearance="@style/TextAppearance.AppCompat"
android:textSize="20sp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_above="@+id/Name" />
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/radioGroup"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="41dp"
android:orientation ="vertical">
<RadioButton
android:id="@+id/Male"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/Gender"
android:layout_alignTop="@+id/Gender"
android:layout_marginEnd="14dp"
android:layout_toStartOf="@+id/Female"
android:checked="true"
android:text="Male" />
<RadioButton
android:id="@+id/Female"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/Male"
android:layout_alignParentEnd="true"
android:layout_alignTop="@+id/Gender"
android:layout_marginEnd="20dp"
android:text="Female" />
</RadioGroup>
<EditText
android:id="@+id/food"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_below="@+id/radioGroup"
android:ems="10"
android:inputType="textPersonName"
android:singleLine="true" />
<EditText
android:id="@+id/age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_below="@+id/food"
android:ems="10"
android:gravity="right"
android:inputType="number"
android:singleLine="true"
android:textColorLink="@android:color/background_light"
android:visibility="visible" />
<EditText
android:id="@+id/weight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_below="@+id/height"
android:ems="10"
android:gravity="right"
android:inputType="numberDecimal"
android:singleLine="true"
android:visibility="visible" />
<EditText
android:id="@+id/height"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_below="@+id/age"
android:ems="10"
android:gravity="right"
android:inputType="numberDecimal"
android:singleLine="true"
android:textIsSelectable="false" />
<Button
android:id="@+id/calc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/weight"
android:layout_centerHorizontal="true"
android:text="Calculate"
android:textColor="?attr/actionMenuTextColor" />
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/calc" />
</RelativeLayout>
这是我的java代码:
public class Calculator extends AppCompatActivity {
EditText weight, height, age, name;
double calculate, result;
RadioButton radioGender;
int selectedId;
private Button button;
TextView calresult;
private Cursor model = null;
private CalculatorHelper helper2 = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calories_calculator);
button = (Button) findViewById(R.id.calc);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
weight = (EditText) findViewById(R.id.weight);
height = (EditText) findViewById(R.id.height);
age = (EditText) findViewById(R.id.age);
name = (EditText) findViewById(R.id.food);
helper2 = new CalculatorHelper(Calculator.this);
model = helper2.getAll();
int Gender;
RadioGroup rg = (RadioGroup) findViewById(R.id.radioGroup);
RadioButton male = (RadioButton) findViewById(R.id.Male);
RadioButton female = (RadioButton) findViewById(R.id.Female);
selectedId = rg.getCheckedRadioButtonId();
radioGender = (RadioButton) findViewById(selectedId);
if (male.isChecked()) {
Gender = 1;
} else {
Gender = 2;
}
if (TextUtils.isEmpty(name.getText().toString())) {
name.setError("Please enter your name");
Toast.makeText(Calculator.this, "Please enter your name",
Toast.LENGTH_LONG).show();
return;
}
if (TextUtils.isEmpty(weight.getText().toString())) {
weight.setError("Please enter your weight");
return;
}
if (TextUtils.isEmpty(height.getText().toString())) {
height.setError("Please enter your height");
return;
}
if (TextUtils.isEmpty(age.getText().toString())) {
age.setError("Please enter your age");
return;
}
String namevr = name.getText().toString();
double weightvr = Double.parseDouble(weight.getText().toString());
double heightvr = Double.parseDouble(height.getText().toString());
int agevr = Integer.parseInt(age.getText().toString());
Intent intent = new Intent(Calculator.this, DataCalculator.class);
intent.putExtra("NAME", namevr);
result = calculate + 0;
intent.putExtra("RESULT", result);
//a.putString("name", String.valueOf(namevr));
if ((weightvr <= 30) || (weightvr >= 200)) {
Toast.makeText(Calculator.this, "Please enter a valid weight",
Toast.LENGTH_SHORT).show();
return;
} else if ((heightvr <= 120) || (heightvr >= 220)) {
Toast.makeText(Calculator.this, "Please enter a valid height",
Toast.LENGTH_SHORT).show();
return;
} else if ((agevr <= 0) || (agevr >= 120)) {
Toast.makeText(Calculator.this, "Please enter a valid age",
Toast.LENGTH_SHORT).show();
return;
} else {
if (selectedId == R.id.Male) {
calculate = (((weightvr * 10) + (heightvr * 6.25)) - (5 * agevr)) + 5;
} else {
calculate = (((weightvr * 10) + (heightvr * 6.25)) - (5 * agevr)) - 161;
}
}
intent.putExtra("RESULT", String.valueOf(calculate));
startActivity(intent);
finish();
}
});
}
}
解决方案
假设 CalculatorHelper 将是您的数据库助手。
第 1 步 - 创建/修改 CallculatorHelper 以
- 扩展 SQLiteOpenHelper 类
即使用public class CalculatorHelper extends SQLiteOpenHelper { ...... }
扩展 SQLiteOpenHelper 的类至少需要 3 个实体
调用 SQLiteOpenHelper 类的超级构造函数的构造函数。
- 此调用需要 4 个值,
- 1)一个有效的上下文,
- 2)数据库的名称(这将是文件的名称),
- 3) 一个 CursorFactory (null 将被用作一个不需要),
- 4) 一个 int 版本号(1 是第一个)。
具有 1 个参数的公共onCreate方法的覆盖
- 已创建的 SQLiteDatabase 对象。该方法不返回任何内容,因此使用 void 定义。
公共onUpgrade方法的覆盖,它传递了 3 个参数
- SQliteDatabase 对象
- 存储在数据库中的版本号(旧版本)
- 已传递给 SQLiteOpenHelper 超级构造函数(新版本)的构造函数的版本号。
通常是您为数据库创建表的位置。
- 当版本增加时,您将在其中对架构进行更改。
但是,除非数据库有一个或更多的表,否则上述内容是无用的。所以真的应该首先设计数据库。
第 2 步(应该是 1)设计
您似乎想保存姓名/食物、体重、身高、年龄和性别。
因此,在不涉及规范化问题等的情况下,假设您希望在单击按钮时存储上述内容。
因此,您需要一个包含名称/食物、体重、身高、年龄和性别列的表格。
SQLite 在数据类型方面非常灵活,但在 SQLite 版本 3 中有 5 种类型的列 TEXT、INTEGER、REAL、NUMERIC 和 BLOB 数据类型
名称/食物将是一个字符串,所以 TEXT. 体重、身高和年龄是整数。没有布尔类型,因此 Gender 将存储为 INTEGER。
因此,您想要一张带有上述内容的表格
该表需要一个名称。所以也许person_data会做。SQLite 使用它的 SQL(结构化查询语言)实现并创建一个表,如果使用SQLite 理解的 CREATE TABLE SQL - CREATE TABLE
所以也许CREATE TABLE person_data (_name TEXT, _weight INTEGER, _height INTEGER, _age INTEGER, _gender INTEGER)
就足够了。- _在任何单词之前使用,以确保避免无效的列名。
强烈建议实体表名、列名等的所有名称使用单一来源的名称。这大大减少了打字错误的机会。因此,建议将这些作为公共静态最终变量添加到数据库帮助程序类中。
要在创建数据库时创建表,可以使用SQLiteDatabase execSQL方法。这是运行不返回结果的 SQL 的一种方法(如果创建表失败,则会导致异常,因为这是不可恢复的情况)。
除非可以插入数据并且通常您希望能够更新数据并可能删除数据,否则该表是无用的。如果可以轻松唯一地识别一行(表中的一个条目),那么能够做到这一点的事情通常会被简化。因此,将添加一个允许唯一标识行的特殊列,实际上没有另外指定该列存在,所以实际上我们正在为该底层列创建一个别名,称为rowid。创建此类列的特殊 SQL 是使用column_name_to_be_the_alias INTEGER PRIMARY KEY
. 对于 android,在某些情况下,列名必须是特定名称(光标适配器),因此有一个名为 BaseColumns._ID 的常量。这将用于列名。
使用 Android SDK 有所谓的便捷方法(它们代表您编写 SQL 并给出一些参数,它们还提供防止 SQL 注入的保护)。将使用 SQLiteDatabase插入、更新和查询方法。
应用以上所有,然后CalculatorHelper.java可以是:-
public class CalculatorHelper extends SQLiteOpenHelper {
public static final String DBNAME = "calculator.db";
public static final int DBVERSION = 1;
public static final String PERSONDATA_TABLENAME = "person_data";
public static final String COL_PERSONDATA_ID = BaseColumns._ID;
public static final String COL_PERSONDATA_NAME = "_name";
public static final String COL_PERSONDATA_WEIGHT = "_weight";
public static final String COL_PERSONDATA_HEIGHT = "_height";
public static final String COL_PERSONDATA_AGE = "_age";
public static final String COL_PERSONDATA_GENDER = "_gender";
public static final String PERSONDATA_TABLESQL = "CREATE TABLE IF NOT EXISTS " +
PERSONDATA_TABLENAME + "(" +
COL_PERSONDATA_ID + " INTEGER PRIMARY KEY," +
COL_PERSONDATA_NAME + " TEXT," +
COL_PERSONDATA_WEIGHT + " INTEGER," +
COL_PERSONDATA_HEIGHT + " INTEGER, " +
COL_PERSONDATA_AGE + " INTEGER, " +
COL_PERSONDATA_GENDER + " INTEGER " +
")";
public CalculatorHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(PERSONDATA_TABLESQL); //<< when the database is created create the table
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public long insertPersonData(String name, int weight, int heigh, int age, boolean gender) {
SQLiteDatabase db = this.getWritableDatabase(); //<< gets the SQLiteDatabase object for this instance
ContentValues cv = new ContentValues(); //<< ContentValues are key (column name) value
cv.put(COL_PERSONDATA_NAME,name);
cv.put(COL_PERSONDATA_WEIGHT,weight);
cv.put(COL_PERSONDATA_HEIGHT,heigh);
cv.put(COL_PERSONDATA_AGE,age);
cv.put(COL_PERSONDATA_GENDER,gender);
//<< NOTE id isn't specified SQLite will generate an id (the value returned)
return db.insert(PERSONDATA_TABLENAME,null,cv);
// Writes and executes the SQL () assuming insertPersonData:-
// INSERT INTO person_data (_name,_weight,_height,_age,_gender) VALUES('Fred',75,160,21,0)
}
/**
*
* @param id The id of the row to be updated
* @param newName The new name to apply ("" or null if not to change)
* @param newWeight The new weight to apply (null or less than 1 to not change)
* @param newHeight as per weight for height
* @param newAge as per weight for age
* @param newGender true or false or null if to not be changed
* @return the number of rows update (should be 1 or 0, o if nothing changed)
*/
public int updatePersonData(long id, String newName, Integer newWeight, Integer newHeight, Integer newAge, Boolean newGender) {
int rv = 0;
ContentValues cv = new ContentValues();
if (newName != null && newName.length() > 0 ) {
cv.put(COL_PERSONDATA_NAME,newName);
}
if (newWeight != null && newWeight > 0) {
cv.put(COL_PERSONDATA_WEIGHT,newWeight);
}
if (newHeight != null && newHeight > 0) {
cv.put(COL_PERSONDATA_HEIGHT,newHeight);
}
if (newAge != null && newAge > 0) {
cv.put(COL_PERSONDATA_AGE,newAge);
}
if (newGender != null) {
cv.put(COL_PERSONDATA_GENDER,newGender);
}
if (cv.size() > 0) {
SQLiteDatabase db = this.getWritableDatabase();
rv = db.update(PERSONDATA_TABLENAME,cv,COL_PERSONDATA_ID + "=?",new String[]{String.valueOf(id)});
}
return rv;
}
public int deletePersonData(long id) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(PERSONDATA_TABLENAME,COL_PERSONDATA_ID+"=?",new String[]{String.valueOf(id)});
}
/**
* Returns ALL persondata as a Cursor object
* @return
*/
public Cursor getAllPersonDataRows() {
SQLiteDatabase db = this.getWritableDatabase();
return db.query(
PERSONDATA_TABLENAME,
null,
null,
null,
null,
null,
null
);
}
public Cursor getPersonByID(long id) {
SQLiteDatabase db = this.getWritableDatabase();
return db.query(
PERSONDATA_TABLENAME,
null,
COL_PERSONDATA_ID+"=?",
null,
null,
null,
null
);
}
}
然后,您可以添加一个按钮,例如将 id 为 save 的按钮添加到布局中,然后使用:-
setContentView(R.layout.calories_calculator); //<<<<<<<<<< existing code
helper2 = new CalculatorHelper(this);
button = (Button) findViewById(R.id.calc); //<<<<<<<<<< existing code
save = (Button) findViewById(R.id.save);
save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Boolean gender = true;
if (((RadioButton)Calculator.this.findViewById(R.id.Male)).isChecked()) {
gender = false;
}
long newid = helper2.insertPersonData(
(((EditText)Calculator.this.findViewById(R.id.food)).getText().toString()),
Integer.parseInt(((EditText)Calculator.this.findViewById(R.id.weight)).getText().toString()),
Integer.parseInt(((EditText)Calculator.this.findViewById(R.id.height)).getText().toString()),
Integer.parseInt(((EditText)Calculator.this.findViewById(R.id.age)).getText().toString()),
gender
);
String msg = "Not Inserted into the database.";
if (newid > 0) {
msg = "Successfully Inserted into the database.";
}
Toast.makeText(Calculator.this,msg,Toast.LENGTH_SHORT).show();
//Example getting data and traversing a Cursor
Cursor csr = helper2.getAllPersonDataRows();
while (csr.moveToNext()) {
String gendertype = "M";
if (csr.getInt(csr.getColumnIndex(CalculatorHelper.COL_PERSONDATA_GENDER)) > 0) {
gendertype = "F";
}
Log.d("PERSONDATA",
"Name is " + csr.getString(csr.getColumnIndex(CalculatorHelper.COL_PERSONDATA_NAME)) +
"\nWeight is " + String.valueOf(
csr.getInt(
csr.getColumnIndex(CalculatorHelper.COL_PERSONDATA_WEIGHT)
)
) + "kg" +
"\nHeight is " + String.valueOf(csr.getInt(csr.getColumnIndex(CalculatorHelper.COL_PERSONDATA_HEIGHT))) + " cm" +
"\nAge is " + csr.getString(csr.getColumnIndex(CalculatorHelper.COL_PERSONDATA_AGE)) + " years" +
"\nGender is " + gendertype +
"\nUnique Row Identifier is " + String.valueOf(csr.getLong(csr.getColumnIndex(CalculatorHelper.COL_PERSONDATA_ID)))
);
}
csr.close(); //<< IMPORTANT to close Cursors when done with them
}
});
//........... rest of your code here ...........
当您单击已添加的SAVE按钮时,然后
- 数据将保存到数据库中。
- Toast 会说它已被添加到数据库中。
- 该日志将包含有关数据库中行的一些输出。
例如,添加 2 行后,日志可能包含:-
07-14 10:15:28.462 25100-25100/s.e.so57021686calculator D/PERSONDATA: Name is Fred
Weight is 75kg
Height is 166 cm
Age is 61 years
Gender is M
Unique Row Identifier is 1
07-14 10:15:28.462 25100-25100/s.e.so57021686calculator D/PERSONDATA: Name is Mary
Weight is 68kg
Height is 34 cm
Age is 159 years
Gender is F
Unique Row Identifier is 2
显示数据已保存(即 Fred 的数据之前已保存)。如果重新启动应用程序并添加另一行,则将显示 3,依此类推。
推荐阅读
- java - 如何将 log4j 与具有动态文件名的多个附加程序一起使用?
- wpf - 将控件添加到 WPF 中从 SQLite 数据库获取数据的 DataGrid 的自动生成的 ColumnHeader
- javascript - 如何使用 C# 验证 Microsoft MVP 配置文件链接是否有效?
- c++ - C++ 模板错误:在“=”标记之前缺少模板参数
- c# - 将xamarin表单应用程序归档到apk后,它不起作用
- excel - 重新安装windows10后VBA代码不运行
- python - 用 Cython 包装 C 标头宏
- node.js - Botframework V4:后处理中间件
- python - win 7 上的 ucrtbase.dll
- python - 为什么python和c++的简单计算结果不同?