zoukankan      html  css  js  c++  java
  • Android

    对于重复的或结构化的数据,保存到数据库中是很好的选择,比如联系人信息。这里假设你对SQL数据库大体上了解然后帮助你学习Android上的SQLite数据库。在Android数据库上需要用到的API可以在android.database.sqlite包中找到。

    定义Schema和Contract

    SQL数据库中一个主要的准测是schema:一个正式的数据库如何组织的声明。这个schema和用来创建数据库的SQL声明是对应的。你会发现创建一个同样的类很有用,叫做contract类,它明确指名了schema在系统中的设计和自己记录的方式。

    contract类是一个常量(URI的名字,表,列)的容器,contract类可以让你在同一个包的其他类中使用同样的常量.这样可以让你只在一个地方改变列名就可以在所有代码中使用。

    一个好的组织contract类的方法是把对于整个数据库全局的定义放到类的根层次。然后为每张表创建内部类来列举它们的列。

    注意:通过实现BaseColumns接口,内部类可以继承一个主键_ID,很多Android类都期望有这个。虽然不是必须的,但是这样可以帮你的数据库和Android framwork和谐的工作。

    例如,这段代码为一个表定义了表明和列名:

     1 public final class FeedReaderContract {
     2     // 为了防止谁意外的实例化contract类
     3     // 给它一个空的构造器
     4     public FeedReaderContract() {}
     5                                              
     6     /* 定义表内容的内部类 */
     7     public static abstract class FeedEntry implements BaseColumns {
     8         public static final String TABLE_NAME = "entry";
     9         public static final String COLUMN_NAME_ENTRY_ID = "entryid";
    10         public static final String COLUMN_NAME_TITLE = "title";
    11         public static final String COLUMN_NAME_SUBTITLE = "subtitle";
    12         ...
    13     }
    14 }

    用SQL助手创建数据库

    一旦定义了数据库长的什么样,然后应该实现创建和维护数据库和表的方法。这里有一些典型了创建和删除表的声明:

     1 private static final String TEXT_TYPE = " TEXT";
     2 private static final String COMMA_SEP = ",";
     3 private static final String SQL_CREATE_ENTRIES =
     4     "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
     5     FeedEntry._ID + " INTEGER PRIMARY KEY," +
     6     FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP +
     7     FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
     8     ... // Any other options for the CREATE command
     9     " )";
    10                                            
    11 private static final String SQL_DELETE_ENTRIES =
    12     "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;

    就和在设备的内部存储上保存文件一样,Android把数据库存储到一个私有的和程序相关的地方。数据是安全的,因为默认的这个区域是不会被其他程序进入的。

    SQLiteOpenHelper类中有很多有用的API。当使用这个类来获得数据库引用时,系统在需要的时候会潜在的长时间运行创建和更新数据库操作,并不是在app启动时。你只需要调用getWritableDatabase()或者getReadableDatabase().

    注意:因为它们可以长时间运行,确保在后台线程中调用getWritableDatabase()或者getReadableDatabase(),比如用AsyncTash或者IntentService

    为了使用SQLiteOpenHelper,创建一个子内然后重写onCreate(),onUpgrade()和onOpen()回调方法。也可以实现onDowngrade(),但是不是必须的。

    例如,这里有一个使用上面方法的SQLiteOpenHelper的实现:

     1 public class FeedReaderDbHelper extends SQLiteOpenHelper {
     2     // 如果改变了数据库的schema,必须要增加数据库的版本。
     3     public static final int DATABASE_VERSION = 1;
     4     public static final String DATABASE_NAME = "FeedReader.db";
     5                                   
     6     public FeedReaderDbHelper(Context context) {
     7         super(context, DATABASE_NAME, null, DATABASE_VERSION);
     8     }
     9     public void onCreate(SQLiteDatabase db) {
    10         db.execSQL(SQL_CREATE_ENTRIES);
    11     }
    12     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    13         // 这个数据库只是缓存在线数据,所以升级方法是丢弃以前的数据然后重新开始
    14         db.execSQL(SQL_DELETE_ENTRIES);
    15         onCreate(db);
    16     }
    17     public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    18         onUpgrade(db, oldVersion, newVersion);
    19     }
    20 }

    为了进入数据库,实例化一个SQLiteOpenHelper的子类:

    1 FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext());

    往数据库存数据

    通过传递ContentValues对象给insert()方法可以往数据库插入数据:

     1 // 获得写模式的数据仓库
     2 SQLiteDatabase db = mDbHelper.getWritableDatabase();
     3                               
     4 //创建一个带值的表,它们的列名是keys
     5 ContentValues values = new ContentValues();
     6 values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id);
     7 values.put(FeedEntry.COLUMN_NAME_TITLE, title);
     8 values.put(FeedEntry.COLUMN_NAME_CONTENT, content);
     9                               
    10 //插入新的行,返回新行的主键值
    11 long newRowId;
    12 newRowId = db.insert(
    13          FeedEntry.TABLE_NAME,
    14          FeedEntry.COLUMN_NAME_NULLABLE,
    15          values);

    inert()的第一个参数是表名,第二个参数提供了一些在ContentValues为空时可以插入NULL的列名(如果把这个设置为null,当没有值时,framework不会插入一行)。 

    从数据库读信息

    为了读数据库,调用query()方法,传递你的选择标准和需要的列。这个方法联合了insert()和update(),期望得到的列是要获得的数据,而不是要插入的数据。结果会在一个Cursor对象中返回。

     1 SQLiteDatabase db = mDbHelper.getReadableDatabase();
     2                         
     3 // 定义一个projection来指定数据库中的那些列在查询后会使用
     4 String[] projection = {
     5     FeedEntry._ID,
     6     FeedEntry.COLUMN_NAME_TITLE,
     7     FeedEntry.COLUMN_NAME_UPDATED,
     8     ...
     9     };
    10                         
    11 // 在resulting Cursor中如何排列结果
    12 String sortOrder =
    13     FeedEntry.COLUMN_NAME_UPDATED + " DESC";
    14                         
    15 Cursor c = db.query(
    16     FeedEntry.TABLE_NAME,  // The table to query
    17     projection,                               // The columns to return
    18     selection,                                // The columns for the WHERE clause
    19     selectionArgs,                            // The values for the WHERE clause
    20     null,                                     // don't group the rows
    21     null,                                     // don't filter by row groups
    22     sortOrder                                 // The sort order
    23     );

    为了查看cursor中的行,使用Cursor的move方法,在读值之前必须要调用。总体上,应该首先调用moveToFirst(),它可以把读的位置指向结果的第一个条。对于每一行,可以调用Cursor的get方法,比如getString()或getLong()来读列的值。对于每个get方法,需要传递期望的列的索引位置,可以通过调用getColumnIndex()或者getColumnIndexOrThrow()来获得。例如:

    1 cursor.moveToFirst();
    2 long itemId = cursor.getLong(
    3     cursor.getColumnIndexOrThrow(FeedEntry._ID)
    4 ); 

    删除数据库信息

    为了删除表中的行,需要提供标识行的选择标准。数据库API提供了一个创建选择标准的机制来防止SQL注入。这个机制把选择的描述分为选择的条款和选择的参数。条款定义了需要查看哪些列,也可以允许组合列查看。参数是一些对应条款的测试的值。因为结果不是按照常规的SQL语句来处理,所以防止了SQL注入。

    1 // Define 'where' part of query.
    2 String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
    3 // Specify arguments in placeholder order.
    4 String[] selectionArgs = { String.valueOf(rowId) };
    5 // Issue SQL statement.
    6 db.delete(table_name, selection, selectionArgs);

    更新数据库

    当需要修改数据库的值时,使用update()方法

    更新表融合了insert()语法的值内容和delete()语法的where。

     1 SQLiteDatabase db = mDbHelper.getReadableDatabase();
     2             
     3 // 列的新值
     4 ContentValues values = new ContentValues();
     5 values.put(FeedEntry.COLUMN_NAME_TITLE, title);
     6             
     7 // 根据ID判断哪一行需要更新
     8 String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
     9 String[] selectionArgs = { String.valueOf(rowId) };
    10             
    11 int count = db.update(
    12     FeedReaderDbHelper.FeedEntry.TABLE_NAME,
    13     values,
    14     selection,
    15     selectionArgs);
     
  • 相关阅读:
    ROS配置C++14环境
    ubantu查看环境变量
    C++指向函数的指针
    ubantu删除文件(夹)
    ROS环境搭建
    vmware workstation pro 安装ubantu虚拟机
    Win7下删除Ubuntu启动项
    ubantu16.04
    ubantu卸载软件
    github之克隆
  • 原文地址:https://www.cnblogs.com/fengquanwang/p/3143360.html
Copyright © 2011-2022 走看看