Android SQLite

就当前的Android开发环境而言,做Android开发似乎变得越来越简单,的确,Android很容易上手,但是要深入理解并学好,却并不简单。从事Android开发一年来,本人最大的忧虑就是基础不扎实。尽管能胜任目前的工作。但是想要进阶,发现前路迷茫。

人最怕的就是不知道自己想要什么,从而徘徊不前。

额,好像扯远了,下面开始今天的重头戏,Android的小型数据库SQLite。

Android的封装使得我们使用数据库变得方便快捷,尽管目前有很多开源的数据库框架供我们去使用,但是理解并使用原生Android系统所提供的API去构建数据库也是必不可少的。

1、创建数据库,必不可少的需要一些固定的字段,表名,已经数据库名的一些常量的定义,在Android开发文档中,定义这些变量,推荐开发者自己创建一个标准的FeedEntry类,这是一个抽象的静态内部类,这个类implements BaseColumns类,在BaseColumms类中有定义两个字段,一个是_id以及_count,通常我们在创建数据库时都会定义一个自增的_id主键,因此,这样的方式,这显得更高逼格了。这里以创建一个评论数据表为例:

public class FeedEntry {

    public FeedEntry() {
    }

    public abstract static class FeedEntryColumn implements BaseColumns {
        //表名
        public final static String TABLE_NAME = "kcomment";
        //昵称
        public final static String KEY_NAME = "name";
        //评论内容
        public final static String KEY_CONTENT = "content";
        //是否是回复
        public final static String KEY_REPLY = "reply";
        //时间
        public final static String KEY_TIME = "time";
        //回复的内容
        public final static String KEY_REPLY_CONTENT = "reply_content";
        //头像
        public final static String KEY_AVATAR = "avatar";
        //信息
        public final static String KEY_INFO = "info";
    }
}

2、Android中使用SQLite我们需要创建一个class去继承SQLiteOpenHelper类,并实现SQLiteOpenHelper中的两个抽象方法onCreate()和onUpgrad()。

public class KDataBase extends SQLiteOpenHelper {

    private final static String DATABASE_NAME = "kcrason.db";
  
    private final static String SQL_CREATE_COMMENT_TABLE = "CREATE TABLE IF NOT EXISTS " +
            FeedEntry.FeedEntryColumn.TABLE_NAME +
            " (" + FeedEntry.FeedEntryColumn._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
            FeedEntry.FeedEntryColumn.KEY_NAME + " VARCHAR(20), " +
            FeedEntry.FeedEntryColumn.KEY_AVATAR + " TEXT, " +
            FeedEntry.FeedEntryColumn.KEY_CONTENT + " TEXT, " +
            FeedEntry.FeedEntryColumn.KEY_TIME + " VARCHAR, " +
            FeedEntry.FeedEntryColumn.KEY_REPLY + " INTEGER, " +
            FeedEntry.FeedEntryColumn.KEY_REPLY_CONTENT + " TEXT, " +
            FeedEntry.FeedEntryColumn.KEY_INFO + " TEXT)";

    public KDataBase() {
        super(KApplication.getContext(), DATABASE_NAME, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL_CREATE_COMMENT_TABLE);
    }
    
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//        String sql = "alter table " + TABLE_COMMENT + " add column info text";
//        db.execSQL(sql);
    }
}

这里很有必要说一下,在首次使用数据库时,其会执行onCreate()方法,而onUpgrade()方法只有在更改onCreate()中的version参数时才会执行。数据库的版本对我们进行数据库的升级很重要。

version=1时创建了一个table_name为Table1的表。
version=2我们需要在表中添加一个字段或者新增一张表(假设为Table2)。
version=3时我们依然是新增一张表。(假设为Table3

那么

onUpgrade()中就需要好好设计。我们注意到在onUpgrade()中返回了oldVersion和newVersion,起初我并不清楚其这样设计的意义。但是如果我们得数据库版本到了version=3的时候,我们就会知道oldVersion的作用了。下面我们详细分析:

当我们数据库的version=3时,而使用version=1/version=2的用户依然存在。

  • 完全新用户,执行onCreate()方法,创建最新的数据库及表,没有什么问题。
  • version=1的用户,此时apk升级后执行onUpgrade()方法,而这时,通过对比oldVersion我们知道,version=1的用户需要创建两个表,即Table2,Table3。
  • version=2的用户,其只需要创建一张表就够了,我们同样可以根据其oldViersion去选择执行哪一段代码。

不容忽视,不容小觑,这就是oldVersion

3、创建好了数据库类之后,我们还需要一个帮助类,来完成数据的存储,更新,删除等一列列操作。

public class KDataBaseHelper {

    private static KDataBaseHelper sKDataBaseHelper;
    private SQLiteDatabase mSQLiteDatabase;
    private KDataBase mKDataBase;

    public static KDataBaseHelper form() {
        synchronized (KDataBaseHelper.class) {
            if (sKDataBaseHelper == null) {
                sKDataBaseHelper = new KDataBaseHelper();
            }
        }
        return sKDataBaseHelper;
    }

    public KDataBaseHelper() {
        mKDataBase = new KDataBase();
    }

}
  • 数据插入
public void insertComment(CommentBean commentBean) {
        mSQLiteDatabase = getSQLDataBase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(FeedEntry.FeedEntryColumn.KEY_NAME, commentBean.name);
        contentValues.put(FeedEntry.FeedEntryColumn.KEY_AVATAR, commentBean.avatar);
        contentValues.put(FeedEntry.FeedEntryColumn.KEY_CONTENT, commentBean.content);
        contentValues.put(FeedEntry.FeedEntryColumn.KEY_REPLY, commentBean.replay);
        contentValues.put(FeedEntry.FeedEntryColumn.KEY_REPLY_CONTENT, commentBean.reply_content);
        contentValues.put(FeedEntry.FeedEntryColumn.KEY_TIME, commentBean.time);
        contentValues.put(FeedEntry.FeedEntryColumn.KEY_INFO, commentBean.info);
        mSQLiteDatabase.insert(FeedEntry.FeedEntryColumn.TABLE_NAME, null, contentValues);
        close(null);
    }
  • 数据更新(此处描述的是更新对应_id值等于id的那一行数据的time的值,如果一次想更新多行数据,则循环即可。想要更新哪些值,就使用ContentValues对象put哪些值)
public void updataCommentData(CommentBean commentBean, String id) {
       mSQLiteDatabase = getSQLDataBase();
       ContentValues contentValues = new ContentValues();
       contentValues.put(FeedEntry.FeedEntryColumn.KEY_TIME, commentBean.time);
       mSQLiteDatabase.update(FeedEntry.FeedEntryColumn.TABLE_NAME, contentValues, "_id=?", new String[]{id});
       close(null);
    }
  • 分页获取数据(curPage:当前页,从0开始计算;limit:每一页的数量)
 public List<CommentBean> getCommentListLimit(int curPage, int limit) {
        String startPosition = String.valueOf(curPage * limit);
        List<CommentBean> commentBeanList = new ArrayList<>();
        mSQLiteDatabase = getSQLDataBase();
        if (mSQLiteDatabase != null) {
            Cursor cursor = mSQLiteDatabase.query(FeedEntry.FeedEntryColumn.TABLE_NAME,
                    new String[]{FeedEntry.FeedEntryColumn._ID,
                            FeedEntry.FeedEntryColumn.KEY_NAME, FeedEntry.FeedEntryColumn.KEY_AVATAR,
                            FeedEntry.FeedEntryColumn.KEY_CONTENT, FeedEntry.FeedEntryColumn.KEY_REPLY,
                            FeedEntry.FeedEntryColumn.KEY_REPLY_CONTENT, FeedEntry.FeedEntryColumn.KEY_TIME,
                            FeedEntry.FeedEntryColumn.KEY_INFO},
                    null, null, null, null, "time DESC", startPosition + "," + limit);
            while (cursor.moveToNext()) {
                CommentBean commentBean = new CommentBean();
                commentBean._id = cursor.getInt(cursor.getColumnIndex(FeedEntry.FeedEntryColumn._ID));
                commentBean.name = cursor.getString(cursor.getColumnIndex(FeedEntry.FeedEntryColumn.KEY_NAME));
                commentBean.avatar = cursor.getString(cursor.getColumnIndex(FeedEntry.FeedEntryColumn.KEY_AVATAR));
                commentBean.content = cursor.getString(cursor.getColumnIndex(FeedEntry.FeedEntryColumn.KEY_CONTENT));
                commentBean.replay = cursor.getInt(cursor.getColumnIndex(FeedEntry.FeedEntryColumn.KEY_REPLY));
                commentBean.reply_content = cursor.getString(cursor.getColumnIndex(FeedEntry.FeedEntryColumn.KEY_REPLY_CONTENT));
                commentBean.time = cursor.getString(cursor.getColumnIndex(FeedEntry.FeedEntryColumn.KEY_TIME));
                commentBean.info = cursor.getString(cursor.getColumnIndex(FeedEntry.FeedEntryColumn.KEY_INFO));
                commentBeanList.add(commentBean);
            }
            close(cursor);
        }
        return commentBeanList;
    }
  • 删除数据库所有数据
public void deleteAllComment() {
        mSQLiteDatabase = getSQLDataBase();
        mSQLiteDatabase.delete(FeedEntry.FeedEntryColumn.TABLE_NAME, null, null);
        close(null);
}
  • 获取数据库所有记录数
public int getCommentCount() {
       mSQLiteDatabase = getSQLDataBase();
       Cursor cursor = mSQLiteDatabase.rawQuery("select count(*) from " + FeedEntry.FeedEntryColumn.TABLE_NAME, null);
       //cursor.moveToFirst()将cursor移动到第一条数据
       cursor.moveToFirst();
       int count = cursor.getInt(0);
       close(cursor);
       return count;
}
  • 关闭数据库及Cursor
private void close(Cursor cursor) {
      if (cursor != null) {
          cursor.close();
      }
      if (mSQLiteDatabase != null) {
          mSQLiteDatabase.close();
      }
}
点赞