【Android 开发实例】时间管理APP开发之数据库设计

版权所有,禁止匿名转载;禁止商业使用。

当然也可以先写界面什么的,但是,总觉得先把数据库后台写好在写界面比较放心。

对于数据库的设计,我一开始没什么概念,甚至不知道如何下手,一开始想着设计成几个表?有哪些字段?

最后用了两天时间,还是一无所获。

最后参照着数据库系统概论课的一些东西以及查看别的项目的源码,才大概的确定数据库。

因为这个APP的类别被我确定只能是二级类别。所以我设计成三个表:

总类表,子类表,详细记录表。

(程序代码中出现的Log语句仅为我自己测试输出使用的)

代码如下:

package suool.net.timesumlbxf.db;
/**
 * Created by SuooL on 2014/10/6.
 */
public class TimeSumDBInfo {
    private static String TableNames[] = {
      "TBL_EXPENDITURE_CATEGORY", // 时间花费类别数据库表
      "TBL_EXPENDITURE_SUB_CATEGORY",    // 时间花费子类别数据库表
      "TBL_EXPENDITURE"    // 时间花费数据库表
    };//表名

    private static String FieldNames[][] = {
      {"ID","NAME"},
      {"ID","NAME","PARENT_CATEGORY_ID"},
      {"ID", "AMOUNT", "EXPENDITURE_CATEGORY_ID",
        "EXPENDITURE_SUB_CATEGORY_ID","DATE", "TIME","MEMO"}
    };//字段名
    private static String FieldTypes[][] = {
      {"INTEGER PRIMARY KEY AUTOINCREMENT","text"},
      {"INTEGER PRIMARY KEY AUTOINCREMENT","TEXT","INTEGER"},
      {"INTEGER PRIMARY KEY AUTOINCREMENT","DOUBLE",
        "INTEGER","INTEGER","TEXT","TEXT","TEXT"}
    };//字段类型
    public TimeSumDBInfo() {
  // TODO Auto-generated constructor stub
    }
    public static String[] getTableNames() {
  return TableNames;
    }
    public static String[][] getFieldNames() {
  return FieldNames;
    }
    public static String[][] getFieldTypes() {
  return FieldTypes;
    }
}


这个是数据库基本属性,具体的数据库创建和方法抽象如下:

package suool.net.timesumlbxf.db;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.nfc.Tag;
import android.util.Log;
import android.widget.Toast;
/**
 * Created by SuooL on 2014/10/6.
 */
public class DBHelper extends SQLiteOpenHelper {
  public static final String TAG = "MyTest";
  private DBHelper mDbHelper; //SQLiteOpenHelper实例对象
  private SQLiteDatabase mDb; //数据库实例对象
  private static DBHelper openHelper = null;//数据库调用实例
  private static String TableNames[];  //表名
  private static String FieldNames[][];   //字段名
  private static String FieldTypes[][];   //字段类型
  private static String NO_CREATE_TABLES = "no tables";
  private static String message = "";
  private final Context mCtx; //上下文实例
  // 构造方法
  private DBHelper(Context context, String myDBName, SQLiteDatabase.CursorFactory factory, int version) {
    super(context, myDBName, factory, version);
    mCtx = context;
  }
  // 获取DBHelper实例
  public static DBHelper getInstance(Context context, String myDBName,
                     SQLiteDatabase.CursorFactory factory, int version) {
    if (openHelper == null) {
      openHelper = new DBHelper(context, myDBName, factory, version);
      TableNames = TimeSumDBInfo.getTableNames();
      FieldNames = TimeSumDBInfo.getFieldNames();
      FieldTypes = TimeSumDBInfo.getFieldTypes();
    }
    Log.d(TAG, "" + TableNames.length);
    return openHelper;
  }
  // 创建数据库动作
  @Override
  public void onCreate(SQLiteDatabase db) {
    if (TableNames == null) {
      message = NO_CREATE_TABLES;
      Log.d(TAG, message);
      return;
    }
    for (int i = 0; i < TableNames.length; i++) {
      String sql2 = "CREATE TABLE " + TableNames[i] + " (";
      for (int j = 0; j < FieldNames[i].length; j++) {
        sql2 += FieldNames[i][j] + " " + FieldTypes[i][j] + ",";
      }
      sql2 = sql2.substring(0, sql2.length() - 1);
      sql2 += ")";
      Log.d(TAG, "自动组装的sql语句."+sql2);
      db.execSQL(sql2);  // 执行语句
    }
    Log.d(TAG,"数据库创建成功.");
  }
  // 更新数据库
  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    for (int i = 0; i < TableNames[i].length(); i++) {
      String sql = "DROP TABLE IF EXISTS " + TableNames[i];  // 存在则删除
      db.execSQL(sql);
    }
    onCreate(db);   // 执行创建数据库语句
  }
  /**
   * 添加数据库相关信息
   */
  public void insertTables(String[] tableNames, String[][] fieldNames, String[][] fieldTypes) {
    TableNames = tableNames;
    FieldNames = fieldNames;
    FieldTypes = fieldTypes;
  }

  /**
   * 关闭数据库
   */
  public void close() {
    mDbHelper.close();
  }
  public void execSQL(String sql) throws java.sql.SQLException {
    mDb.execSQL(sql);
  }
  /**
   * sql语句查询数据
   */
  public Cursor rawQuery(String sql, String[] selectionArgs) {
    Cursor cursor = mDb.rawQuery(sql, selectionArgs);
    return cursor;
  }
  /**
   * 查询数据
   */
  public Cursor select(String table, String[] columns,
             String selection, String[] selectionArgs, String groupBy,
             String having, String orderBy) {
    Cursor cursor = mDb.query
        (
            table, columns, selection, selectionArgs,
            groupBy, having, orderBy
        );
    return cursor;
  }
  /**
   * 添加数据
   */
  public long insert(String table, String fields[], String values[]) {
    ContentValues cv = new ContentValues();
    for (int i = 0; i < fields.length; i++) {
      cv.put(fields[i], values[i]);
    }
    return mDb.insert(table, null, cv);
  }
  /**
   * 删除数据
   */
  public int delete(String table, String where, String[] whereValue) {
    return mDb.delete(table, where, whereValue);
  }
  /**
   * 更新数据
   */
  public int update(String table, String updateFields[],
            String updateValues[], String where, String[] whereValue) {
    ContentValues cv = new ContentValues();
    for (int i = 0; i < updateFields.length; i++) {
      cv.put(updateFields[i], updateValues[i]);
    }
    return mDb.update(table, cv, where, whereValue);
  }
  /**
   * 错误信息: 不为null数据库未建立
   */
  public String getMessage() {
    return message;
  }
}


数据相关的默认字段值如下,计划着这些项目都是可以实现自定义添加和删除的。

<?xml version="1.0" encoding="utf-8"?>

<resources>
  <!-- 时间花费项目 -->
  <string-array name="TBL_EXPENDITURE_CATEGORY">
    <item>学习</item>
    <item>工作</item>
    <item>娱乐</item>
    <item>欢乐时光</item>
    <item>日常MISSION</item>
  </string-array>
  <!-- 时间花费子项目 -->
  <!-- 学习子项目 -->
  <string-array name="TBL_EXPENDITURE_SUB_CATEGORY_1">
    <item>基础语言</item>
    <item>脚本语言</item>
    <item>Linux编程</item>
    <item>Android</item>
    <item>技术类书籍OR博客</item>
  </string-array>
  <!-- 工作项目 -->
  <string-array name="TBL_EXPENDITURE_SUB_CATEGORY_2">
    <item>APP</item>
    <item>外包程序</item>
  </string-array>
  <!-- 娱乐子项目 -->
  <string-array name="TBL_EXPENDITURE_SUB_CATEGORY_3">
    <item>电脑游戏</item>
    <item>手机游戏</item>
    <item>社交网络</item>
    <item>Music</item>
  </string-array>
  <!-- 欢乐时光子项目 -->
  <string-array name="TBL_EXPENDITURE_SUB_CATEGORY_4">
    <item>文学阅读</item>
    <item>博客写作</item>
    <item>体育锻炼</item>
    <item>陪黎怡</item>
  </string-array>
  <!-- 日常任务列表 -->
  <string-array name="TBL_EXPENDITURE_SUB_CATEGORY_5">
    <item>2道算法题目</item>
    <item>单词50个或英语阅读</item>
    <item>技术博文1篇</item>
    <item>技术文章+笔记</item>
    <item>电子书1小时</item>
  </string-array>
  <!-- -->
  <string-array name="Hour">
    <item>0</item>
    <item>1</item>
    <item>2</item>
    <item>3</item>
    <item>4</item>
    <item>5</item>
  </string-array>
  <string-array name="Minute">
    <item>0</item>
    <item>10</item>
    <item>20</item>
    <item>30</item>
    <item>40</item>
    <item>50</item>
  </string-array>
</resources>

在上面的时间长度被我固定了,其实用户自己输入任意数值,我刚开始是考虑有用户输入值,但是,后来一想觉得这个时间长度实在不是很精确的事情(做某件事具体的开始和结束界限不清,而且某段时间不一定全部用来做某件事),因此与其让用户花费时间计算精确,不如给个大概值选择就好。(四舍五入)。

ok,数据库的设计就是这样,做完这个感觉其实数据库的设计并不难,只要自己能够分析出所做的东西的focus在哪里就好了。

这个APP核心数据其实就是记录,这个记录包括类别,时间,时间长度等字段值。

但是又不可能只设计一个表,因为设计一个表不利于查询,而且造成数据冗余。因此就会产生将数据库设计成我上面代码所示的样子。

当然这里只是提供我的思路,其他更好的设计必然存在,希望您能够指导学习。

0 0