09 SQLite数据库

SQLite数据库

应用沙盒目录

/data/data/com.example.criminalintent

SQLite的特点

  • SQLite使用单个文件存储数据,使用SQLite库读取数据。
  • 创建表字段时,不需要指定字段类型。

定义Schema

创建com.example.criminalintent.database.CrimeDbSchema类,定义数据表:

public class CrimeDbSchema {
    //数据表
    public static final class CrimeTable {
        //表名
        public static final String NAME = "crimes";
        //表的字段
        public static final class Cols {
            public static final String UUID = "uuid";
            public static final String TITLE = "title";
            public static final String DATE = "date";
            public static final String SOLVED = "solved";
        }
    }
}

创建初始数据库

创建数据库时,建议总是遵循以下步骤。

  1. 确认目标数据库是否存在。

  2. 如果不存在,首先创建数据库,然后创建数据库表以及必需的初始化数据。

  3. 如果存在,打开并确认CrimeDbSchema是否是最新版本。

  4. 如果是旧版本,就运行相关代码升级到最新版本。

Android提供的 SQLiteOpenHelper 类可以帮我们处理这些。在数据库包中创
建 CrimeBaseHelper 类:

public class CrimeBaseHelper extends SQLiteOpenHelper {
    private static final int VERSION = 1;
    private static final String DATABASE_NAME = "crimeBase.db";

    public CrimeBaseHelper(Context context) {
        super(context, DATABASE_NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //执行创建数据表的SQL语句
        db.execSQL("create table " + CrimeTable.NAME +
                "(" + " _id integer primary key autoincrement, " +
                CrimeTable.Cols.UUID + ", " +
                CrimeTable.Cols.TITLE + ", " +
                CrimeTable.Cols.DATE + ", " +
                CrimeTable.Cols.SOLVED + ")"
        );
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
}

在CrimeLab中用CrimeBaseHelper创建crime数据库:

public class CrimeLab {
    private static CrimeLab sCrimeLab;

    private Context mContext;
    private SQLiteDatabase mDatabase;

    private CrimeLab(Context context) {
        mContext = context.getApplicationContext();
        mDatabase = new CrimeBaseHelper(mContext).getWritableDatabase();    //创建/打开数据库
    }
}

写入数据库

使用ContentValues

CrimeLab.java

//根据crime创建ContentValues并返回
private static ContentValues getContentValues(Crime crime) {
    ContentValues values = new ContentValues();
    values.put(CrimeTable.Cols.UUID, crime.getId().toString());
    values.put(CrimeTable.Cols.TITLE, crime.getTitle());
    values.put(CrimeTable.Cols.DATE, crime.getDate().getTime());
    values.put(CrimeTable.Cols.SOLVED, crime.isSolved() ? 1 : 0);

    return values;
}

插入记录

CrimeLab.java

//添加新的陋习
public void addCrime(Crime crime) {
    ContentValues values = getContentValues(crime);
    /**
     * 向数据库表中插入记录
     * @param table String 数据库表名
     * @param nullColumnHack String
     * @param values ContentValues 要写入的数据
     * @return long
     */
    mDatabase.insert(CrimeTable.NAME, null, values);
}

更新记录

CrimeLab.java

//更新陋习
public void updateCrime(Crime crime) {
    String uuidString = crime.getId().toString();
    ContentValues values = getContentValues(crime);
    /**
     * 更新数据库表中的记录
     * @param table String
     * @param values ContentValues
     * @param whereClause String
     * @param whereArgs String[]
     * @return int
     */
    mDatabase.update(CrimeTable.NAME, values, CrimeTable.Cols.UUID + " = ?", new String[] { uuidString });
}
更新Crime数据

在CrimeFragment中修改Crime实例后,通过覆盖CrimeFragment.onPause()方法完成更新:

CrimeFragment.java

@Override
public void onPause() {
    super.onPause();

    //修改crime内容后需要更新
    CrimeLab.get(getActivity()).updateCrime(mCrime);
}

查询记录

CrimeLab.java

//查询陋习
private CrimeCursorWrapper queryCrimes(String whereClause, String[] whereArgs) {
    /**
     * 查询数据库表中的记录
     * @param table
     * @param columns
     * @param selection
     * @param selectionArgs
     * @param groupBy
     * @param having
     * @param orderBy
     * @return Cursor
     */
    Cursor cursor = mDatabase.query(
            CrimeTable.NAME,
            null,
            whereClause,
            whereArgs,
            null,
            null,
            null
    );

    return new CrimeCursorWrapper(cursor);
}
使用CursorWrapper

cursor是个表数据处理工具,其任务是封装数据表中的原始字段值。

新增Crime类的构造方法
public Crime() {
    this(UUID.randomUUID());
}

public Crime(UUID id) {
    mId = id;
    mDate = new Date();
}
新建CrimeCursorWrapper类
public class CrimeCursorWrapper extends CursorWrapper {
    public CrimeCursorWrapper(Cursor cursor) {
        super(cursor);
    }

    public Crime getCrime() {
        String uuidString = getString(getColumnIndex(CrimeTable.Cols.UUID));
        String title = getString(getColumnIndex(CrimeTable.Cols.TITLE));
        long date = getLong(getColumnIndex(CrimeTable.Cols.DATE));
        int isSolved = getInt(getColumnIndex(CrimeTable.Cols.SOLVED));

        Crime crime = new Crime(UUID.fromString(uuidString));
        crime.setTitle(title);
        crime.setDate(new Date(date));
        crime.setSolved(isSolved != 0);

        return crime;
    }
}
返回Crime列表

CrimeLab.java

//获得所有陋习
public List<Crime> getCrimes() {
    List<Crime> crimes = new ArrayList<>();
    CrimeCursorWrapper cursor = queryCrimes(null, null);

    try {
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            crimes.add(cursor.getCrime());
            cursor.moveToNext();
        }
    }
    finally {
        cursor.close();
    }

    return crimes;
}
返回指定ID的Crime

CrimeLab.java

//获得指定ID的陋习
public Crime getCrime(UUID id) {
    CrimeCursorWrapper cursor = queryCrimes(
            CrimeTable.Cols.UUID + " = ?",
            new String[] { id.toString() }
    );

    try {
        if (cursor.getCount() == 0) return null;
        cursor.moveToFirst();
        return cursor.getCrime();
    }
    finally {
        cursor.close();
    }
}

更新模型层数据

虽然 Cirme 记录已存入数据库,但数据读取还未完善,编辑完新的crime后,尝试点击回退按钮,CrimePagerActivity 并没有相应刷新。

这是因为 CrimeLab 的工作方式已经改变。以前,只有一个 List<Crime> ,而且每个 Crime在 List<Crime> 中只存有一个对象,要获取哪个 Crime 只能去找 mCrimes 。现在,mCrimes 已废弃不用了。因此,getCrimes() 方法返回的 List<Crime> 是 Crime 对象的快照。要刷新 CrimeListActivity 界面,首先要更新这个快照。

CrimeListFragment.CrimeAdapter

public void setCrimes(List<Crime> crimes) {
    mCrimes = crimes;
}

然后在updateUI()方法中调用setCrimes(List<Crime>)方法:

CrimeListFragment.java

//为RecyclerView设置Adapter
private void updateUI() {
    CrimeLab crimeLab = CrimeLab.get(getActivity());
    List<Crime> crimes = crimeLab.getCrimes();

    if (mAdapter == null) {
        mAdapter = new CrimeAdapter(crimes);
        mCrimeRecyclerView.setAdapter(mAdapter);
    }
    else {
        mAdapter.setCrimes(crimes);
        mAdapter.notifyDataSetChanged();
    }

    //设置工具栏子标题
    updateSubtitle();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值