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

提到安卓的数据库存储,很多开发者都会想到使用继承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);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
	}

	@Override
	public 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 ):

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

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

果然是这样,查看ContextImpl extends Context

@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
	return openOrCreateDatabase(name, mode, factory, null);
}

@Override
public 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) {// 包含有 FileNotFoundException
				e.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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值