数据库工具:Room

Room结构

导入依赖

app的build.gradle中开启kapt:

apply plugin: 'kotlin-kapt'

并导入以下依赖:

def room_version = '2.2.4'
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor
// Test helpers
testImplementation "androidx.room:room-testing:$room_version"
kapt 'android.arch.persistence.room:compiler:1.1.1'
implementation 'androidx.recyclerview:recyclerview:1.1.0' //注意:对于基于 Kotlin 的应用,请确保使用 kapt 而不是 annotationProcessor。您还应添加 kotlin-kapt 插件。

基础三大件:Entity,Dao,Database

Entity:数据库的结构

语法
使用@Entity注解Entity类
使用@PrimaryKey(autoGenerate = true),@ColumuInfo(name = "")注解键
示例
@Entity(tableName = "word_table")     //数据库结构
data class Word (
@PrimaryKey(autoGenerate = true)
var id: Int,
@ColumnInfo(name = "english")
var word: String,
@ColumnInfo(name = "chinese")
var chineseMeaning: String
)

Dao:数据库的操作

语法
使用 @Dao注解接口
使用 @Insert,@Update,@Delete,@Query("DELETE FROM WORD"),@Query("SELECT * FROM WORD ORDER BY ID DESC") 等注解数据库操作
示例
@Dao        //数据库操作
interface WordDao {
@Insert
fun insertWords(vararg words: Word) @Update
fun updateWords(vararg words: Word) @Delete
fun daleteWords(vararg words: Word) @Query("DELETE FROM WORD")
fun deleteAllWords() @Query("SELECT * FROM WORD ORDER BY ID DESC")
fun getAllWords() : LiveData<List<Word>> //使用LiveData,观测数据改变并自动
}

Database:数据库工具类

语法
使用 @Database(entities = [com.example.roomtest.Word::class], version = 1, exportSchema = false) 注解类
尽量使用抽象类并且使用单例模式
示例
@Database(entities = [com.example.roomtest.Word::class], version = 1, exportSchema = false)
//获取数据库实体
abstract class WordDatabase : RoomDatabase() {
abstract fun getWordDao() : WordDao /**
* 单例数据库
*/
companion object {
private var instance: WordDatabase? = null
@Synchronized
fun get(context: Context): WordDatabase {
if (instance == null) {
instance = Room.databaseBuilder(context.applicationContext,
WordDatabase::class.java, "word_database")
.build()
}
return instance!!
}
}
}

进阶

一、使用ViewModel

1,导入ViewModel模板
2,示例
class WordViewModel(application: Application) : AndroidViewModel(application) {
var wordDao: WordDao
var allWordLive: LiveData<List<Word>> init {
val wordDatabase = WordDatabase.get(application)
wordDao = wordDatabase.getWordDao()
allWordLive = wordDao!!.getAllWords()
} fun insertWords(vararg words: Word) {
InsertAsyncTask(wordDao!!).execute(*words)
} fun clearWords() {
ClearAsyncTask(wordDao!!).execute()
} inner class InsertAsyncTask(val wordDao: WordDao) : BaseAsyncTask(wordDao) {
override fun doInBackground(vararg params: Word): Void? {
wordDao.insertWords(*params)
return null
}
}
inner class UpdateAsyncTask(val wordDao: WordDao) : BaseAsyncTask(wordDao) {
override fun doInBackground(vararg params: Word): Void? {
return null
}
}
inner class DeleteAsyncTask(val wordDao: WordDao) : BaseAsyncTask(wordDao) {
override fun doInBackground(vararg params: Word): Void? {
return null
}
}
inner class ClearAsyncTask(val wordDao: WordDao) : BaseAsyncTask(wordDao) {
override fun doInBackground(vararg params: Word): Void? {
wordDao.deleteAllWords()
return null
}
} }

以上ViewModel将数据的操作与使用放在一起,还可以继续分层:将数据的使用剥离出去

二、使用仓库Reposity访问数据

示例
/**
* 数据访问
*/
class WordRepository(val context: Context) {
private var allWordsLive : LiveData<List<Word>>
private var wordDao : WordDao init {
val wordDatabase = WordDatabase.get(context)
wordDao = wordDatabase.getWordDao()
allWordsLive = wordDao.getAllWords()
} fun insertWords(vararg words: Word) {
InsertAsyncTask(wordDao!!).execute(*words)
} fun clearWords() {
ClearAsyncTask(wordDao!!).execute()
} inner class InsertAsyncTask(val wordDao: WordDao) : BaseAsyncTask(wordDao) {
override fun doInBackground(vararg params: Word): Void? {
wordDao.insertWords(*params)
return null
}
} inner class ClearAsyncTask(val wordDao: WordDao) : BaseAsyncTask(wordDao) {
override fun doInBackground(vararg params: Word): Void? {
wordDao.deleteAllWords()
return null
}
}
}

改造后的ViewModel:

class WordViewModel(application: Application) : AndroidViewModel(application) {
private val wordDao: WordDao
var allWordLive: LiveData<List<Word>> init {
val wordDatabase = WordDatabase.get(application)
wordDao = wordDatabase.getWordDao()
allWordLive = wordDao!!.getAllWords()
} fun insertWords(vararg words: Word) {
WordRepository(getApplication()).insertWords(*words)
} fun clearWords() {
WordRepository(getApplication()).clearWords()
}
}

三、升级数据库

Room.databaseBuilder(context.applicationContext,
WordDatabase::class.java,
"word_database")
.fallbackToDestructiveMigration() //破坏式升级:升级版本后清空原有内容
.addMigrations(MIGRATION_1_2) //无痛改变
.build() val MIGRATION_1_2 : Migration = object : Migration(1, 2) { //类的参数分别为新旧数据库的版本号
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("") //使用SQL语句进行数据库操作
}
}

项目的其他代码

基累BaseAsyncTask:

open class BaseAsyncTask(private val wordDao: WordDao) : AsyncTask<Word, Void, Void>() {
override fun doInBackground(vararg words: Word): Void? {
return null
}
}

Acitvity:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import java.lang.StringBuilder class MainActivity : AppCompatActivity() { private lateinit var insert: Button
private lateinit var update: Button
private lateinit var delete: Button
private lateinit var clear: Button
private lateinit var content : TextView private lateinit var wordViewModel: WordViewModel override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) insert = findViewById(R.id.insert)
update = findViewById(R.id.update)
delete = findViewById(R.id.delete)
clear = findViewById(R.id.clear)
content = findViewById(R.id.content) wordViewModel = ViewModelProviders.of(this)[WordViewModel::class.java] wordViewModel.allWordLive.observe(this, Observer {
var text = StringBuilder()
for (x in it) {
text.append(x.id).append(":").append(x.word).append("=").append(x.chineseMeaning).append("\n")
}
content.text = text.toString()
}) insert.setOnClickListener {
var word1 = Word(0, "Hello", "你好")
var word2 = Word(0, "World", "世界")
wordViewModel.insertWords(word1, word2)
} clear.setOnClickListener {
wordViewModel.clearWords()
}
}
}

xml布局:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"> <androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.6" /> <ScrollView
android:id="@+id/scrollView2"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0"> <TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="24sp" />
</ScrollView> <androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" /> <androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.8" /> <Button
android:id="@+id/insert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="insert"
app:layout_constraintBottom_toTopOf="@+id/guideline3"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline"
app:layout_constraintVertical_bias="0.52" /> <Button
android:id="@+id/update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="update"
app:layout_constraintBottom_toTopOf="@+id/guideline3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline2"
app:layout_constraintTop_toTopOf="@+id/guideline"
app:layout_constraintVertical_bias="0.52" /> <Button
android:id="@+id/clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="clear"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline3" /> <Button
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delete"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline2"
app:layout_constraintTop_toTopOf="@+id/guideline3" />
</androidx.constraintlayout.widget.ConstraintLayout>

懒加载控件:Paging

声明依赖

def paging_version = "2.1.1"
implementation "androidx.paging:paging-runtime:$paging_version" // For Kotlin use paging-runtime-ktx
// alternatively - without Android dependencies for testing
testImplementation "androidx.paging:paging-common:$paging_version" // For Kotlin use paging-common-ktx
// optional - RxJava support
implementation "androidx.paging:paging-rxjava2:$paging_version" // For Kotlin use paging-rxjava2-ktx

Paging + Room + RecyclerView

数据类型

Dao中,数据使用DataSource.Factory<Key, Value>格式

@Dao
interface StudentDao {
@Query("SELECT * FROM student_table ORDER BY id")
fun getAllStudents() : DataSource.Factory<Int, Student>
}

RecycleView的适配器

改用PagedListAdapter<数据类型, Holder>:

class MyPagedAdapter : PagedListAdapter<Student, MyViewHolder>(DIFF_CALLBACK) {
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Student>() {
override fun areItemsTheSame(oldItem: Student, newItem: Student): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Student, newItem: Student):Boolean {
return oldItem.studentNumber == newItem.studentNumber
}
}
} override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(view)
} override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
} class MyViewHolder(itemView: View) : ViewHolder(itemView) {
}
}

装配数据

private lateinit var studentDao: StudentDao						//Dao类
private lateinit var studentDatabase : StudentDatabase //数据库类
private lateinit var pagedAdapter: MyPagedAdapter //适配器类
private lateinit var allStudentsLivePaged : LiveData<PagedList<Student>> //分页数据管理 override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) pagedAdapter = MyPagedAdapter()
list.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
list.adapter = pagedAdapter studentDatabase = StudentDatabase.getInstance(this)
studentDao = studentDatabase.getStudentDao() //第二个参数为一次加载数据的个数
allStudentsLivePaged = LivePagedListBuilder(studentDao.getAllStudents(), 2).build()
}

最新文章

  1. [斜率优化DP]【学习笔记】【更新中】
  2. JDBC中的Statement和PreparedStatement的区别
  3. 数据结构:单链表结构字符串(python版)添加了三个新功能
  4. jQuery DataTables 行获取
  5. BZOJ1113 海报PLA
  6. 天大 ACM 1090. City hall
  7. jQuery事件绑定方法bind、 live、delegate和on的区别
  8. SQL Server 2005------函数
  9. CCNA网络工程师学习进程(7)路由器的路由配置
  10. adb报错:The connection to adb is down, and a severe&amp;nbs
  11. java8之stream
  12. linux 文件权限的基础知识
  13. [SCOI 2016]背单词
  14. wget Mac OS 下安装
  15. AX_Query
  16. LeetCode - Top K Frequent Words
  17. (线段树 区间运算求点)Flowers -- hdu -- 4325
  18. Filter与Servlet的区别与联系
  19. 【BZOJ 4558】 4558: [JLoi2016]方 (计数、容斥原理)
  20. 【OpenCV】解析OpenCV中copyMakerBorder函数

热门文章

  1. 第二十七篇 -- QTreeWidget总结
  2. vue函数式组件详解
  3. 冒泡排序(bubble_sort)——Python实现
  4. 【干货】WordPress系统级更新,程序升级
  5. Android 自定义属性(attrs)、样式(Style)、主题(Theme)
  6. Git 修改历史 commits 中的用户名和邮箱
  7. rot位移密码详解(rot5、rot13、rot18、rot47)
  8. [开源]C++实现控制台随机迷宫
  9. Linux守护进程及Systemd
  10. spring学习05(代理模式)