涉及到內(nèi)部數(shù)據(jù)庫的創(chuàng)建使用。
外部數(shù)據(jù)庫的導(dǎo)入。
kotlin的文件讀寫。
最近在寫一個學(xué)習(xí)資料類的應(yīng)用。
現(xiàn)在寫到題庫部分。
思路是:事先準(zhǔn)備好外部的數(shù)據(jù)庫(就是題庫了),然后,程序第一次運(yùn)行時候,首先創(chuàng)建內(nèi)部數(shù)據(jù)庫,然后將外部數(shù)據(jù)庫復(fù)制到內(nèi)置,外置數(shù)據(jù)庫文件在assets里面。內(nèi)置的在/data/data/com.包名/databases/數(shù)據(jù)庫名
首先寫一個SQL類,用來創(chuàng)建程序內(nèi)置數(shù)據(jù)庫,這個數(shù)據(jù)庫結(jié)構(gòu)和外部要一致!初始化是空的。
mySql類:用來初始化內(nèi)置類,程序運(yùn)行第一次會初始化一個數(shù)據(jù)庫
class mySql(context: Context,name:String,version:Int ):SQLiteOpenHelper(context,name,null,version) {val Create_ = "Create table sj(id integer primary key autoincrement,name varchar);"//SQL語句與平時用的SQL一致,創(chuàng)建試卷表val mContext = contextvar sjs = arrayListOf<Map<String, Any>>()//存放數(shù)據(jù),試卷表的數(shù)據(jù)override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {//這是以后用來升級數(shù)據(jù)庫用的,暫時不用}override fun onCreate(db: SQLiteDatabase?) {//繼承的是help數(shù)據(jù)庫類,這個方法會在新建對象時候調(diào)用。try {db!!.execSQL(Create_)//強(qiáng)制執(zhí)行SQLLog.d("dbInit","")//這個方法,會檢測數(shù)據(jù)庫是否存在,存在將不會再重新創(chuàng)建!Toast.makeText(mContext, "初始化數(shù)據(jù)庫", Toast.LENGTH_SHORT).show()} catch (e: NullPointerException) {println(e)}}//這里是查詢fun wen_query( db: SQLiteDatabase, hand: Handler): Boolean {xxxreturn false}}
在main活動里:初始化這個數(shù)據(jù)庫對象(不用擔(dān)心以后會被覆蓋)
val temSql = mySql(this@MainActivity,"glx",1)//初始化數(shù)據(jù)庫//參數(shù):context,數(shù)據(jù)庫名,版本(隨意)
然后,我們就要把外置的數(shù)據(jù)庫復(fù)制過來了。
看看ImportDB類,用來復(fù)制我們外面的數(shù)據(jù)庫文件:這里一定注意,會有很多問題出現(xiàn)。
class ImportDB internal constructor(private val context: Context) {private val BUFFER_SIZE =10000//一會下面會按照字節(jié)讀取//伴生對象,在主活動里,檢測是否存在數(shù)據(jù)庫文件會用到companion object {val DB_NAME = "glx" //保存的數(shù)據(jù)庫文件名val PACKAGE_NAME = "com.simplewen.win0"//工程包名val DB_PATH = ("/data${Environment.getDataDirectory().absolutePath}/$PACKAGE_NAME/databases") //在手機(jī)里存放數(shù)據(jù)庫的位置}fun copyDatabase():Boolean{val dbfile = "$DB_PATH/$DB_NAME"Log.d("look",dbfile)try {//執(zhí)行數(shù)據(jù)庫導(dǎo)入val db = this.context.resources.assets.open("glx") //欲導(dǎo)入的數(shù)據(jù)庫val fos = FileOutputStream(dbfile)val buffer = ByteArray(BUFFER_SIZE)var count = 0//這里很多小伙伴一定看到過java版的,AS一鍵轉(zhuǎn)kt,會出現(xiàn)一個問題!,//就是:count=db.read出現(xiàn)在了while里面,這會報紅,kt不支持在while語句出現(xiàn)賦值語句,要用匿名函數(shù)。while ({ count = db.read(buffer);count}() > 0) {fos.write(buffer, 0, count)}fos.close()//關(guān)閉輸出流db.close()//關(guān)閉輸入流return true}catch (e: Throwable) {Log.d("look",e.toString())e.printStackTrace()return false}}}
我們看看主活動:這里思路,當(dāng)數(shù)據(jù)庫初始化以后,我們開始導(dǎo)入外部數(shù)據(jù)庫,如果導(dǎo)入完成,設(shè)置flag為1,下次啟動檢測,防止重復(fù)導(dǎo)入。
val file = File(ImportDB.DB_PATH + "/glx")//調(diào)用伴生對象Log.d("here",ImportDB.DB_PATH)val share = getSharedPreferences("dbFlag", Activity.MODE_PRIVATE)if (file.exists()){//內(nèi)部數(shù)據(jù)庫存在,開始導(dǎo)入外部Toast.makeText(this@MainActivity, "存在內(nèi)部數(shù)據(jù)庫", Toast.LENGTH_SHORT).show()if(share.getString("dbFlag","0") == "1"){Toast.makeText(this@MainActivity, "已經(jīng)導(dǎo)入過數(shù)據(jù)庫", Toast.LENGTH_SHORT).show()}else{val inDb = ImportDB(this@MainActivity)if(inDb.copyDatabase()){Toast.makeText(this@MainActivity, "復(fù)制完成", Toast.LENGTH_SHORT).show()val shareP = getSharedPreferences("dbFlag", Activity.MODE_PRIVATE)val edit = shareP.edit()edit.putString("dbFlag","1")//導(dǎo)入完成,設(shè)置標(biāo)志edit.apply()}else{Toast.makeText(this@MainActivity, "復(fù)制失敗", Toast.LENGTH_SHORT).show()}}}
最后,看看具體使用:在另一個FG里面使用:這個時候,由于數(shù)據(jù)庫已經(jīng)存在,再初始化一個對象,將會默認(rèn)使用新的數(shù)據(jù)庫。
調(diào)用,db.query(xxx)...
val temSql = mySql(activity,"glx",1)xxxval db = temSql.writableDatabase
好了,這個問題,網(wǎng)上太多java的資料了,kt很少,這里和kt小伙伴分享一下,小總結(jié)。