安卓中的几种使用SQLite的方法

来源:互联网 发布:飓风打印软件 编辑:程序博客网 时间:2024/06/04 20:02

提到安卓的数据库存储,很多开发者都会想到使用继承SQLiteOpenHelper,然后使用安卓框架中给出的接口进行数据库和数据表的创建、删除、更新。

然而,因为安卓的sdk中封装了接口,让我在很长的一段时间内都认为数据库的使用只能通过SQLiteOpenHelper来操作。其实还有其他方式,一般有:

1 直接继承SQLiteOpenHelper,调用它的getReadableDatabase和getWritableDatabase进行操作。

2 使用FileOutputStream把assets目录下的数据库拷贝到应用的安装目录下进行操作。

3 使用openOrCreateDatabase直接创建一个db文件,并且execSQL相关的表进去。

4 直接使用openOrCreateDatabase打开一个sd卡或者其他路径下的数据库进行CRUD。


实现SQLiteOpenHelper

在onCreate()中对数据库进行创建,然后使用getReadableDatabase和getWritableDatabase得到 SQLiteDatabase 实例,然后进行操作。

public class DemoSqlOpenHelper extends SQLiteOpenHelper  {private static DemoSqlOpenHelper helper;public DemoSqlOpenHelper getIns(Context context){if(helper == null){helper = new DemoSqlOpenHelper(context, "demo.db", null, 1);}return helper;}public DemoSqlOpenHelper(Context context, String name,CursorFactory factory, int version,DatabaseErrorHandler errorHandler) {super(context, name, factory, version, errorHandler);}public DemoSqlOpenHelper(Context context, String name,CursorFactory factory, int version) {super(context, name, factory, version);}@Overridepublic void onCreate(SQLiteDatabase db) {}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}public void test(){helper.getReadableDatabase();helper.getWritableDatabase();}}

可以查看到操作数据库的接口:

在android.database.sqlite.SQLiteOpenHelper下查看getReadableDatabase()和getWritableDatabase()的具体实现:

读和写分别使用一个bool值进行区分:

public SQLiteDatabase getReadableDatabase() {synchronized (this) {    return getDatabaseLocked(false);}}public SQLiteDatabase getWritableDatabase() {synchronized (this) {    return getDatabaseLocked(true);}}private SQLiteDatabase getDatabaseLocked(boolean writable) {······try {    if (DEBUG_STRICT_READONLY && !writable) {final String path = mContext.getDatabasePath(mName).getPath();db = SQLiteDatabase.openDatabase(path, mFactory,SQLiteDatabase.OPEN_READONLY, mErrorHandler);    } else {db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,mFactory, mErrorHandler);    }} catch (SQLiteException ex) {    if (writable) {throw ex;    }    Log.e(TAG, "Couldn't open " + mName    + " for writing (will try read-only):", ex);    final String path = mContext.getDatabasePath(mName).getPath();    db = SQLiteDatabase.openDatabase(path, mFactory,    SQLiteDatabase.OPEN_READONLY, mErrorHandler);}······}

这里调用到了Context中的openOrCreateDatabase()方法,从命名可以比较清晰的猜到这是打开或者创建数据库的接口,所以,数据库的创建是在调用到openOrCreateDatabase()的时候才会执行也就是调用getReadableDatabase()和getWritableDatabase(),new一个SQLiteOpenHelper是不会创建数据库的,也就是SQLiteOpenHelper中的onCreate()也是在。那么现在应该进入到Context里面了解具体的实现:

进入发现Context中发现这个方法没有被实现,只是抽象类

public abstract SQLiteDatabase openOrCreateDatabase(String name,            int mode, CursorFactory factory, DatabaseErrorHandler errorHandler);

进入子类(ContextWrapper extends Context ):

@Overridepublic SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {return mBase.openOrCreateDatabase(name, mode, factory);}

发现也没有被实现,那么就是在接口中实现了:

果然是这样,查看ContextImpl extends Context

@Overridepublic SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {return openOrCreateDatabase(name, mode, factory, null);}@Overridepublic SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,    DatabaseErrorHandler errorHandler) {File f = validateFilePath(name, true);int flags = SQLiteDatabase.CREATE_IF_NECESSARY;if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) {    flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;}SQLiteDatabase db = SQLiteDatabase.openDatabase(f.getPath(), factory, flags, errorHandler);setFilePermissionsFromMode(f.getPath(), mode, 0);return db;}

这里调用了SQLiteDatabase的静态方法。
SQLiteDatabase.openDatabase
查看openDatabase方法:直到这里才创建了一个数据库实例SQLiteDatabase。

public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags,    DatabaseErrorHandler errorHandler) {SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler);db.open();return db;}

至此,完全打开了一个数据库,可以看到:

过程中调用了静态方法 SQLiteDatabase.openDatabase().


使用assets目录下的数据库文件

编译apk的时候把数据库文件也编写进去,使用FileOutputStream流把数据库文件拷贝到应用安装的data/data/dtabases/目录下。


拷贝到安装目录下之后,操作同第一种方式:

public class CopyAssetsDB {private Context context;private String DBNAME = "TestDemo.db";private final int BUFFER_SIZE = 400000;private String databasePath = null;private SQLiteDatabase db = null;public CopyAssetsDB(Context context) {super();this.context = context;StringBuilder builder = new StringBuilder();builder.append("/data");builder.append(Environment.getDataDirectory().getAbsolutePath());//等同data/builder.append("/");builder.append(context.getPackageName());builder.append("/");builder.append(DBNAME);databasePath = builder.toString();Log.i(getClass().getSimpleName(),"DBPath="+databasePath);}public SQLiteDatabase openDatabase() {if(db != null){return db;}File file = new File(databasePath);if (!file.exists()) {InputStream is;try {is = context.getResources().getAssets().open(DBNAME);FileOutputStream fos = new FileOutputStream(databasePath);byte[] buffer = new byte[BUFFER_SIZE];int count = 0;while ((count = is.read(buffer)) > 0) {fos.write(buffer, 0, count);//写入ROM中}Log.i(getClass().getSimpleName(),"数据库文件不存在,创建文件");fos.close();is.close();} catch (IOException e) {// 包含有 FileNotFoundExceptione.printStackTrace();}}else{Log.i(getClass().getSimpleName(),"数据库文件存在,直接打开");}db = SQLiteDatabase.openOrCreateDatabase(databasePath, null);return db;}}

openOrCreateDatabase直接创建db文件

public class CreateDB {private static final String DATABASE_NAME = "myDatabase.db";private static final String DATABASE_TABLE = "mainTable";private static final String DATABASE_CREATE ="create table " + DATABASE_TABLE +"( _id integer primary key autoincrement," +"column_one text not null);"; SQLiteDatabase myDatabase; public void createDatabase(Context context) {myDatabase = context.openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);myDatabase.execSQL(DATABASE_CREATE);}}

操作sd卡路径下的数据库

操作SD卡请别忘记相关的permission:
<!-- 在SD卡中创建和删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 往SD卡写入数据的权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

public class OpensdCardDB {private SQLiteDatabase db;private String databasePath = null;private String DBNAME = "TestDemo.db";public OpensdCardDB() {super();StringBuilder path = new StringBuilder();path.append(Environment.getExternalStorageDirectory());path.append("/");path.append(DBNAME);databasePath = path.toString();}public SQLiteDatabase openDB(){db = SQLiteDatabase.openOrCreateDatabase(databasePath, null);return db;}}

不一定只有这几种方式,还有其他更多的方式,比如网络上down下来的数据库文件。

完成之后使用SQLiteDatabase进行操作:

private SQLiteDatabase database;/** *  查询数据 */private void query(){Cursor c = database.rawQuery("select * from Student", null);if(c.moveToFirst()){do{StringBuilder builder = new StringBuilder();builder.append(c.getString(0)+" , ");builder.append(c.getString(1)+" , ");builder.append(c.getString(2));Log.i(getClass().getSimpleName(),"读取结果为="+builder.toString());}while(c.moveToNext());}else{Log.i(getClass().getSimpleName(),"读取结果为=null");}}/** * 插入数据 */private void insert(){Cursor c = database.rawQuery("insert into Student values('hello','18','女')", null);boolean result = c.moveToFirst();}

直到得到SQLiteDatabase对象即可对使用封装在安卓SDK中的接口继续数据库操作.


转载请联系作者并且注明出处http://blog.csdn.net/dreamintheworld/article/details/38665195



0 0
原创粉丝点击