首页 > 解决方案 > 如何创建一个 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();
        }
    });

}

}

标签: androidsqlite

解决方案


假设 CalculatorHelper 将是您的数据库助手。

第 1 步 - 创建/修改 CallculatorHelper 以

  • 扩展 SQLiteOpenHelper 类

即使用public class CalculatorHelper extends SQLiteOpenHelper { ...... }

扩展 SQLiteOpenHelper 的类至少需要 3 个实体

  1. 调用 SQLiteOpenHelper 类的超级构造函数的构造函数。

    • 此调用需要 4 个值,
    • 1)一个有效的上下文,
    • 2)数据库的名称(这将是文件的名称),
    • 3) 一个 CursorFactory (null 将被用作一个不需要),
    • 4) 一个 int 版本号(1 是第一个)。
  2. 具有 1 个参数的公共onCreate方法的覆盖

    • 已创建的 SQLiteDatabase 对象。该方法不返回任何内容,因此使用 void 定义。
  3. 公共onUpgrade方法的覆盖,它传递了 3 个参数

    • SQliteDatabase 对象
    • 存储在数据库中的版本号(旧版本)
    • 已传递给 SQLiteOpenHelper 超级构造函数(新版本)的构造函数的版本号。
  4. 通常是您为数据库创建表的位置。

  5. 当版本增加时,您将在其中对架构进行更改。

但是,除非数据库有一个或更多的表,否则上述内容是无用的。所以真的应该首先设计数据库。

第 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,依此类推。


推荐阅读