日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Android Jetpack 库架构组件 Room+Paging 基础使用

發(fā)布時(shí)間:2023/12/13 综合教程 30 生活家
生活随笔 收集整理的這篇文章主要介紹了 Android Jetpack 库架构组件 Room+Paging 基础使用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上篇文章 Android Jetpack 庫架構(gòu)組件 ViewModel+LiveData 基礎(chǔ)使用 的示例2中,使用 ViewModel+ LiveData 的方式實(shí)現(xiàn)了數(shù)據(jù)庫數(shù)據(jù)查詢并分頁顯示的效果,而這里的數(shù)據(jù)庫用的就是Room,分頁使用的 Paging。

Room 是什么

Room 持久性庫在 SQLite 的基礎(chǔ)上提供了一個(gè)抽象層,讓用戶能夠在充分利用 SQLite 的強(qiáng)大功能的同時(shí),獲享更強(qiáng)健的數(shù)據(jù)庫訪問機(jī)制。

也就是 Room 是在SQlite的基礎(chǔ)上封裝了接口,使得SQlite更加易用。

使用Room需要包含 3 個(gè)主要組件:

數(shù)據(jù)庫:包含數(shù)據(jù)庫持有者??梢酝ㄟ^調(diào)用 Room.databaseBuilder()Room.inMemoryDatabaseBuilder() 獲取 Database 的實(shí)例。
Entity:表示數(shù)據(jù)庫中的表。
DAO:包含用于訪問數(shù)據(jù)庫的方法。

Room 不同組件之間的關(guān)系如下圖所示:

步驟1:應(yīng)用使用 Room 數(shù)據(jù)庫來獲取與該數(shù)據(jù)庫關(guān)聯(lián)的數(shù)據(jù)訪問對(duì)象 (DAO)。:
步驟2:應(yīng)用使用每個(gè) DAO 從數(shù)據(jù)庫中獲取實(shí)體,然后再將對(duì)這些實(shí)體的所有更改保存回?cái)?shù)據(jù)庫中。
步驟3:應(yīng)用使用實(shí)體來獲取和設(shè)置與數(shù)據(jù)庫中的表列相對(duì)應(yīng)的值。

Room 使用步驟

示例:
(1)獲取數(shù)據(jù)庫中學(xué)生的姓名列表

Module -> build.gradle的引入

版本依賴查看:https://developer.android.google.cn/jetpack/androidx/releases/room

	def room_version = "2.2.5"

    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor

	// 還有一些可選項(xiàng),可查看上面的版本依賴鏈接

定義實(shí)體類,用@Entity注解

@Entity(tableName = "Student")
data class Student(
	// 字段1,主鍵自增
	@PrimaryKey(autoGenerate = true) 
	val id: Int, 
	// 字段2
	val name: String)
    

創(chuàng)建 DAO接口,用@Dao注解實(shí)現(xiàn)數(shù)據(jù)庫的增刪改查

@Dao
interface StudentDao {

	// DataSource.Factory<Int, Student> 獲取 Room 數(shù)據(jù)庫中所有學(xué)生名稱按升序返回
    @Query("SELECT * FROM Student ORDER BY name COLLATE NOCASE ASC")
    fun getAllStudent(): DataSource.Factory<Int, Student>

	// 插入學(xué)生集合
    @Insert
    fun insert(students: List<Student>)

	// 插入一個(gè)學(xué)生
    @Insert
    fun insert(student: Student)
}

創(chuàng)建AppDatabase擴(kuò)展 RoomDatabase 的抽象類,并創(chuàng)建數(shù)據(jù)庫實(shí)例。

// 把實(shí)體類添加到數(shù)組中,定義數(shù)據(jù)庫版本號(hào)
@Database(entities = [Student::class], version = 1)
abstract class StudentDb:RoomDatabase() {
    // 定義 DAO
    abstract fun studentDao(): StudentDao
	
	// 靜態(tài)方法創(chuàng)建實(shí)例和往數(shù)據(jù)庫插入學(xué)生姓名信息
    companion object {
        private var instance: StudentDb? = null
        @Synchronized
        fun get(): StudentDb {
            if (instance == null) {
                instance = Room.databaseBuilder(applicationContext,
                    StudentDb::class.java, "StudentDatabase").build()
            }
            return instance!!
        }
        // 默認(rèn)數(shù)據(jù)
        fun initData(){
            ioThread {
                // 單線程池
                get().studentDao().insert(
                    CHEESE_DATA.map {
                        Student(
                            id = 0,
                            name = it
                        )
                    })
            }
        }
    }
}

// 學(xué)生姓名
private val CHEESE_DATA = arrayListOf(
    "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
    "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag",
    "Airedale", "Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert",  // 15
    "American Cheese", "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro",
    "Appenzell", "Aragon", "Ardi Gasna", "Ardrahan", "Armenian String",
    "Aromes au Gene de Marc", "Asadero", "Asiago", "Aubisque Pyrenees", "Autun", // 30
    "Avaxtskyr", "Baby Swiss", "Babybel", "Baguette Laonnaise", "Bakers",
    "Baladi", "Balaton", "Bandal", "Banon", "Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",
    "Baylough", "Beaufort", "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
    "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir", "Bierkase", "Bishop Kennedy",
    "Blarney", "Bleu d'Auvergne", "Bleu de Gex", "Bleu de Laqueuille",
    "Bleu de Septmoncel", "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
    "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini", "Bocconcini (Australian)"
)

獲取數(shù)據(jù),展示

class HomeViewModel(context: Context): BaseViewModel() {

    companion object {
        private const val PAGE_SIZE = 15
        private const val ENABLE_PLACEHOLDERS = false
    }

//    val mContext = context
//    val dao = StudentDb.get(mContext).studentDao()

	// 獲取 DAO,通過 DAO 去獲取數(shù)據(jù)庫數(shù)據(jù)
    val dao = StudentDb.get().studentDao()
    // dao.getAllStudent() 這里即返回了所有的學(xué)生姓名
	
	// 這里使用 Paging 實(shí)現(xiàn)分頁,文章下面再說。
    val allStudents = LivePagedListBuilder(dao.getAllStudent(), PagedList.Config.Builder()
        .setPageSize(PAGE_SIZE)                         //配置分頁加載的數(shù)量
        .setEnablePlaceholders(ENABLE_PLACEHOLDERS)     //配置是否啟動(dòng)PlaceHolders
        .setInitialLoadSizeHint(PAGE_SIZE)              //初始化加載的數(shù)量
        .build()).build()
}

Tip:
別忘了在Application調(diào)用數(shù)據(jù)的初始化,不然查詢數(shù)據(jù)庫時(shí)查不到學(xué)生數(shù)據(jù)。(或者你編寫學(xué)生姓名一條條插入數(shù)據(jù)庫)

// 初始化數(shù)據(jù)庫數(shù)據(jù)
StudentDb.initData()

Paging 是什么

分頁庫可幫助您一次加載和顯示一小塊數(shù)據(jù)。按需載入部分?jǐn)?shù)據(jù)會(huì)減少網(wǎng)絡(luò)帶寬和系統(tǒng)資源的使用量。

分頁庫的關(guān)鍵組件是 PagedList 類,用于加載應(yīng)用數(shù)據(jù)塊或頁面。隨著所需數(shù)據(jù)的增多,系統(tǒng)會(huì)將其分頁到現(xiàn)有的 PagedList 對(duì)象中。

如果任何已加載的數(shù)據(jù)發(fā)生更改,會(huì)從 LiveData 或基于 RxJava2 的對(duì)象向可觀察數(shù)據(jù)存儲(chǔ)器發(fā)出一個(gè)新的 PagedList 實(shí)例。
隨著 PagedList 對(duì)象的生成,應(yīng)用界面會(huì)呈現(xiàn)其內(nèi)容,同時(shí)還會(huì)考慮界面控件的生命周期。

分頁庫支持以下數(shù)據(jù)架構(gòu):

僅從后端服務(wù)器提供,推薦配合 Retrofit 使用。
僅存儲(chǔ)在設(shè)備上的數(shù)據(jù)庫中,推薦配合 Room 使用。
使用設(shè)備上的數(shù)據(jù)庫作為緩存的其他來源組合,推薦配合 Retrofit + Room 使用。

下面以查詢數(shù)據(jù)庫顯示在RecyclerView為例介紹使用步驟。

Paging 使用步驟

示例:
(1)將數(shù)據(jù)庫的數(shù)據(jù)查詢出來顯示在 RecyclerView

Module -> build.gradle的引入

版本依賴查看:https://developer.android.google.cn/jetpack/androidx/releases/paging

dependencies {
   def paging_version = "2.1.2"

   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
 }
    

構(gòu)建對(duì)象。Room 數(shù)據(jù)庫提供了 DataSource.Factory 對(duì)象或者 自定義對(duì)象

@Dao
interface StudentDao {
	
    @Query("SELECT * FROM Student ORDER BY name COLLATE NOCASE ASC")
    fun getAllStudent(): DataSource.Factory<Int, Student>
}

生成PagedList。將 DataSource.Factory 的實(shí)例傳遞到 LivePagedListBuilderRxPagedListBuilder 對(duì)象。

class HomeViewModel(context: Context): BaseViewModel() {

    companion object {
        private const val PAGE_SIZE = 15
        private const val ENABLE_PLACEHOLDERS = false
    }

    val dao = StudentDb.get().studentDao()
	
	// 傳遞實(shí)例給 LivePagedListBuilder ,分頁配置
    val allStudents = LivePagedListBuilder(dao.getAllStudent(), PagedList.Config.Builder()
        .setPageSize(PAGE_SIZE)                         //配置分頁加載的數(shù)量
        .setEnablePlaceholders(ENABLE_PLACEHOLDERS)     //配置是否啟動(dòng)PlaceHolders
        .setInitialLoadSizeHint(PAGE_SIZE)              //初始化加載的數(shù)量
        .build()).build()
}

創(chuàng)建 Adapter繼承PagedListAdapter
PagedListAdapter繼承自RecyclerView.Adapter

PagedListAdapter需要接收一個(gè)DiffUtil.ItemCallback參數(shù)進(jìn)行對(duì)象的構(gòu)建。

class StudentAdapter: PagedListAdapter<Student, StudentViewHolder>(diffCallback) {

    override fun onBindViewHolder(holder: StudentViewHolder, position: Int) {
        holder.bindTo(getItem(position))
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StudentViewHolder =
        StudentViewHolder(parent)

    companion object {
    
    	// 用于計(jì)算列表中兩個(gè)非空 item 之間的差異的回調(diào)。
        private val diffCallback = object : DiffUtil.ItemCallback<Student>() {
        
        	// 檢查兩個(gè)對(duì)象是否表示同一 item 數(shù)據(jù)。
            override fun areItemsTheSame(oldItem: Student, newItem: Student): Boolean =
                oldItem.id == newItem.id
			
			// 檢查兩個(gè)項(xiàng)目是否具有相同的數(shù)據(jù)。
            override fun areContentsTheSame(oldItem: Student, newItem: Student): Boolean =
                oldItem == newItem
        }
    }
}

UI頁面使用數(shù)據(jù)

override fun initView() {

    val adapter = StudentAdapter()
    val layoutManager = LinearLayoutManager(activity)
    rv_list.layoutManager = layoutManager
    rv_list.adapter = adapter
    
    // 將數(shù)據(jù)的變化反映到UI上
    viewModel.allStudents.observe(this, Observer {
        adapter.submitList(it)
    })
}

詳細(xì)使用代碼請(qǐng)參見:YGragon/FrameDemo

總結(jié)

Paging是分頁庫,也就是將大量的數(shù)據(jù)通過一段一段的返回給頁面展示。而大量的數(shù)據(jù)可以從網(wǎng)絡(luò)請(qǐng)求返回,也可以是從Room數(shù)據(jù)庫中讀取。從Room數(shù)據(jù)庫中讀取需要?jiǎng)?chuàng)建數(shù)據(jù)庫實(shí)例、DAO、Entity,而將數(shù)據(jù)展示在列表需要用到PagedListAdapter。PagedListAdapter繼承自RecyclerView.Adapter,在該Adapter中需要傳入diffCallback,用于判斷數(shù)據(jù)是否是最新的。最后就是在UI中通過LiveData監(jiān)聽數(shù)據(jù)的變化及時(shí)更新到 UI。

參考

room
Room-declaring_dependencies
paging
Paging-declaring_dependencies
分頁配置

上車

佛系原創(chuàng)號(hào)主

總結(jié)

以上是生活随笔為你收集整理的Android Jetpack 库架构组件 Room+Paging 基础使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。