android中Room資料庫的基本使用

来源:https://www.cnblogs.com/bddm/p/18185922
-Advertisement-
Play Games

簡介: 還在使用原生的sqllite?有這麼清爽且穩如狗的room為啥不用呢? Room是Google官方推薦使用的資料庫,相比較某些優秀資料庫框架來說,不用過於擔心某天庫會停止維護,且訪問資料庫非常流暢,並且提供了與常規的ORM框架一樣,通過添加編譯期註解來進行表和欄位的配置,譬如@Databas ...


簡介:

還在使用原生的sqllite?有這麼清爽且穩如狗的room為啥不用呢?

Room是Google官方推薦使用的資料庫,相比較某些優秀資料庫框架來說,不用過於擔心某天庫會停止維護,且訪問資料庫非常流暢,並且提供了與常規的ORM框架一樣,通過添加編譯期註解來進行表和欄位的配置,譬如@Database、@Dao、@Entity、@Query、@Insert、@Update、@Detele等的註解,可以使用簡單代碼實現相比以前SQLite更複雜的代碼的效果,這點兒有點兒類似於java世界里的mybatis。總而言之, Room功能強大,速度和穩定性不弱,還簡單易用,算得上是一個優秀的資料庫。

PS:

Demo以kotlin代碼為例,kotlin最近剛在學O.o?java應該也是類似的。插入代碼時沒有看到kotlin語言選項,代碼標識可能顯示js,複製代碼註意包名~

Demo展示效果:

 

Demo案例參考官網教程:

kotlin官網教程鏈接:https://developer.android.com/codelabs/android-room-with-a-view-kotlin?hl=zh-cn#0

 這個鏈接可能需要神奇的力量,也可以使用梯子打開新世界的大門~

架構組件:

LiveData、ViewModel 和 Room

 

  • LiveData:一種可監測的數據存儲器類。務必保存/緩存最新版本的數據,併在數據發生變化時通知其監測者。LiveData 具有生命周期感知能力。界面組件只是監測相關數據,不會停止或恢復監測。LiveData 將自動管理所有這些操作,因為它在監測時可以感知相關的生命周期狀態變化。
  • ViewModel:充當存儲庫(數據)和界面之間的通信中心。對於界面而言,數據來源不再是一個需要關註的問題。ViewModel 實例在重新創建 activity/fragment 後仍然存在。
  • 存儲庫:您創建的類,主要用於管理多個數據源。
  • 實體:使用 Room 時用於描述資料庫表的帶註解的類。
  • Room 資料庫:可簡化資料庫工作,並充當 SQLite 底層資料庫的接入點(隱藏 SQLiteOpenHelper)。它使用 DAO 向 SQLite 資料庫發出查詢請求。
  • SQLite 資料庫:設備上的存儲空間。Room 持久性庫會為您創建和維護此資料庫。
  • DAO:數據訪問對象。從 SQL 查詢到函數的映射。在使用 DAO 時,您需要調用相應方法,其餘操作均由 Room 完成。

依賴添加:

在app(應用模塊)下的build.gradle(app)中添加
apply plugin: 'kotlin-kapt'

dependencies {
    // ... 省略無關
    // 
room
    implementation "androidx.room:room-runtime:$rootProject.roomVersion"
    implementation "androidx.room:room-ktx:$rootProject.roomVersion"
    kapt "androidx.room:room-compiler:$rootProject.roomVersion"
    androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
}
在項目下的build.gradle(project)中添加
ext {
    roomVersion = '2.1.0-alpha06'
   //... 省略無關
}

項目結構:

 

使用步驟:

1.創建entity 創建一個Kotlin類,用於表示資料庫中的一個表,表名為"word_table"。
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "word_table")
class Word(@PrimaryKey @ColumnInfo(name = "word") val word: String)

@Entity(tableName = "word_table"): 這是一個註解,用於標識這個Kotlin類是一個Room資料庫實體。tableName參數指定了在資料庫中對應的表名為"word_table"。Room是一個Android持久性庫,用於簡化資料庫訪問,併在編譯時進行SQL查詢驗證。

class Word: 這是一個Kotlin類的聲明,類名為Word,用於表示資料庫中的一個條目。通常,一個Entity類會映射到資料庫中的一張表,每個實例則代表表中的一行數據。

@PrimaryKey @ColumnInfo(name = "word") val word: String: 這是Word類的一個屬性,表示資料庫表中的一個列。這個屬性被@PrimaryKey註解標記,表示它是表中的主鍵。主鍵是唯一標識資料庫表中每一行的欄位。@ColumnInfo(name = "word")指定了這個屬性在資料庫表中對應的列名為"word"。val word: String定義了一個名為word的不可變屬性,類型為String,用於存儲單詞的值。

這段代碼定義了一個名為Word的資料庫實體類,它映射到資料庫中的"word_table"表,包含一個名為"word"的主鍵列,用於存儲單詞的字元串值。

 

2.創建Dao

創建一個Kotlin介面,用於定義訪問資料庫中word_table表的操作

 1 import androidx.room.Dao
 2 import androidx.room.Insert
 3 import androidx.room.OnConflictStrategy
 4 import androidx.room.Query
 5 import com.example.roomwordsample.datac.Word
 6 import kotlinx.coroutines.flow.Flow
 7 
 8 @Dao
 9 interface WordDao {
10     @Query("select * from word_table order by word asc")
11     fun getAlphabetizedWords(): Flow<List<Word>>
12 
13     @Insert(onConflict = OnConflictStrategy.IGNORE)
14      fun insert(word:Word)
15 
16     @Query("DELETE FROM word_table")
17       fun deleteAll()
18 }

 

@Dao: 這是一個註解,標識這個Kotlin介面是一個Room資料庫訪問對象(DAO)。DAO(Data Access Object)用於定義資料庫操作的方法。

interface WordDao: 這是一個Kotlin介面的聲明,用於定義與單詞表相關的資料庫操作方法。

@Query("select * from word_table order by word asc"): 這是一個註解,用於標識一個查詢操作。在這裡,它指定了一個SQL查詢,從"word_table"表中選擇所有列,並按照"word"列的升序排列。這個方法返回一個Flow<List<Word>>對象,表示查詢結果以流的形式返回,其中每個元素都是一個Word對象的列表。

fun getAlphabetizedWords(): Flow<List<Word>>: 這是一個抽象方法,用於執行查詢操作,並返回結果。

@Insert(onConflict = OnConflictStrategy.IGNORE): 這是一個註解,用於標識一個插入操作。onConflict = OnConflictStrategy.IGNORE指定了當插入的數據與現有數據發生衝突時,忽略新數據。這個方法用於將一個Word對象插入到資料庫中。

fun insert(word: Word): 這是一個抽象方法,用於執行插入操作。

@Query("DELETE FROM word_table"): 這是一個註解,用於標識一個刪除操作。它指定了一個SQL刪除語句,從"word_table"表中刪除所有數據。

fun deleteAll(): 這是一個抽象方法,用於執行刪除操作。

這個介面定義了三種操作:獲取按字母順序排列的單詞列表、插入單詞到資料庫中以及刪除資料庫中所有的單詞。

  3.創建RoomDatabase 定義一個用於創建和管理資料庫的類,主要使用了Room Persistence Library。
 1 import android.content.Context
 2 import androidx.room.Database
 3 import androidx.room.Room
 4 import androidx.room.RoomDatabase
 5 import androidx.sqlite.db.SupportSQLiteDatabase
 6 import com.example.roomwordsample.dao.WordDao
 7 import com.example.roomwordsample.datac.Word
 8 import kotlinx.coroutines.CoroutineScope
 9 import kotlinx.coroutines.launch
10 
11 @Database(entities = arrayOf(Word::class), version = 1, exportSchema = false)
12 public abstract class WordRoomDatabase :RoomDatabase(){
13     abstract fun wordDao(): WordDao
14 
15     private class WordDatabaseCallback(
16         private val scope: CoroutineScope
17     ) : RoomDatabase.Callback() {
18 
19         override fun onCreate(db: SupportSQLiteDatabase) {
20             super.onCreate(db)
21             INSTANCE?.let { database ->
22                 scope.launch {
23                     populateDatabase(database.wordDao())
24                 }
25             }
26         }
27 
28         suspend fun populateDatabase(wordDao: WordDao) {
29             // Delete all content here.
30             wordDao.deleteAll()
31 
32             // Add sample words.
33             var word = Word("Hello")
34             wordDao.insert(word)
35             word = Word("World!")
36             wordDao.insert(word)
37 
38             // TODO: Add your own words!
39         }
40     }
41 
42     companion object {
43         // Singleton prevents multiple instances of database opening at the
44         // same time.
45         @Volatile
46         private var INSTANCE: WordRoomDatabase? = null
47 
48         fun getDatabase(
49             context: Context,
50             scope: CoroutineScope
51         ): WordRoomDatabase  {
52             return INSTANCE ?: synchronized(this) {
53                 val instance = Room.databaseBuilder(
54                     context.applicationContext,
55                     WordRoomDatabase::class.java,
56                     "word_database"
57                 )
58                 .addCallback(WordDatabaseCallback(scope))
59                 .allowMainThreadQueries()
60                 .build()
61                 INSTANCE = instance
62                 // return instance
63                 instance
64             }
65         }
66     }
67 }

@Database(entities = arrayOf(Word::class), version = 1, exportSchema = false): 這是一個註解,用於標識這個類是一個Room資料庫類。entities參數指定了資料庫中的實體類,這裡只有一個Word類。version參數指定了資料庫的版本號,如果你更新了資料庫結構,需要增加版本號以執行相應的資料庫遷移。exportSchema參數指定是否導出資料庫的schema到文件中,這裡設置為false表示不導出。

public abstract class WordRoomDatabase : RoomDatabase(): 這是一個抽象類,繼承自RoomDatabase類,用於定義資料庫操作。它包含了一個抽象方法wordDao(),用於獲取WordDao介面的實例。

private class WordDatabaseCallback(...) : RoomDatabase.Callback() {...}: 這是一個內部類,繼承自RoomDatabase.Callback類,用於在資料庫被創建時執行一些操作。在這個例子中,它在資料庫創建時調用了populateDatabase()方法,用於初始化資料庫。

companion object {...}: 這是一個伴生對象,包含了一些靜態方法和屬性。其中INSTANCE是一個WordRoomDatabase的單例實例,使用了雙重校驗鎖來確保線程安全。

fun getDatabase(...): 這是一個靜態方法,用於獲取資料庫實例。如果實例為空,則創建一個新的資料庫實例,併在創建時調用WordDatabaseCallback來初始化資料庫。

populateDatabase(wordDao: WordDao): 這是一個掛起函數,用於在資料庫創建時初始化資料庫內容。在這個例子中,它刪除了資料庫中的所有內容,然後插入了兩個示例單詞"Hello"和"World!",你也可以添加自己的單詞。

這個類負責創建和管理資料庫,定義了資料庫的版本、實體、以及初始化操作。

 

4.創建Repository

創建一個簡單的Repository類,用於連接ViewModel和DAO(Data Access Object)。

 1 import androidx.annotation.WorkerThread
 2 import com.example.roomwordsample.dao.WordDao
 3 import com.example.roomwordsample.datac.Word
 4 import kotlinx.coroutines.flow.Flow
 5 
 6 class  WordRepository(private val wordDao: WordDao){
 7 
 8     val allWords: Flow<List<Word>> = wordDao.getAlphabetizedWords()
 9 
10     @Suppress("RedundantSuspendModifier")
11     @WorkerThread
12     suspend fun insert(word: Word) {
13         wordDao.insert(word)
14     }
15 }

import語句: 這些是導入所需的類和包,包括androidx.annotation.WorkerThread、com.example.roomwordsample.dao.WordDao、com.example.roomwordsample.data.Word和kotlinx.coroutines.flow.Flow。這些類用於定義數據流以及DAO介面。

class WordRepository(private val wordDao: WordDao): 這是一個Kotlin類的聲明,表示WordRepository類。它包含一個私有屬性wordDao,類型為WordDao,用於對資料庫進行操作。

val allWords: Flow<List<Word>> = wordDao.getAlphabetizedWords(): 這是一個屬性,用於獲取從資料庫中獲取的所有單詞。它是一個Flow<List<Word>>類型的屬性,表示這是一個數據流,可以觀察到資料庫中單詞列表的變化。

@Suppress("RedundantSuspendModifier") @WorkerThread suspend fun insert(word: Word): 這是一個插入操作的掛起函數。@WorkerThread註解表示該函數應該在工作線程中執行,通常用於防止在主線程中執行長時間運行的操作。suspend關鍵字表示這是一個掛起函數,可以在協程中調用。

wordDao.insert(word): 這是調用WordDao介面的插入方法,將單詞插入到資料庫中。

這個Repository類負責從DAO獲取數據,並暴露一個數據流以供ViewModel觀察。它還包含一個方法用於在資料庫中插入新的單詞。

 

5.創建ViewModel

 定義了一個ViewModel類(WordViewModel)以及一個用於創建ViewModel實例的工廠類(WordViewModelFactory)。

 1 import androidx.lifecycle.LiveData
 2 import androidx.lifecycle.ViewModel
 3 import androidx.lifecycle.ViewModelProvider
 4 import androidx.lifecycle.asLiveData
 5 import androidx.lifecycle.viewModelScope
 6 import com.example.roomwordsample.datac.Word
 7 import com.example.roomwordsample.repository.WordRepository
 8 import kotlinx.coroutines.launch
 9 
10 class WordViewModel(private val repository: WordRepository) : ViewModel() {
11 
12     val allWords: LiveData<List<Word>> = repository.allWords.asLiveData()
13 
14     /**
15      * Launching a new coroutine to insert the data in a non-blocking way
16      */
17     fun insert(word: Word) = viewModelScope.launch {
18         repository.insert(word)
19     }
20 }
21 
22 class WordViewModelFactory(private val repository: WordRepository) : ViewModelProvider.Factory {
23     override fun <T : ViewModel> create(modelClass: Class<T>): T {
24         if (modelClass.isAssignableFrom(WordViewModel::class.java)) {
25             @Suppress("UNCHECKED_CAST")
26             return WordViewModel(repository) as T
27         }
28         throw IllegalArgumentException("Unknown ViewModel class")
29     }
30 }

class WordViewModel(private val repository: WordRepository) : ViewModel() {...}:

WordViewModel是一個ViewModel類,用於管理與單詞相關的數據和用戶界面狀態。
它有一個名為repository的私有屬性,類型為WordRepository,用於與數據層交互。
allWords是一個LiveData對象,用於保存從數據層獲取的所有單詞列表。通過調用repository.allWords.asLiveData(),將數據流轉換為LiveData對象,以便在UI層觀察數據變化。
insert是一個公共方法,用於向數據層插入新的單詞。它啟動一個新的協程(coroutine),在非阻塞的方式下執行插入操作。


class WordViewModelFactory(private val repository: WordRepository) : ViewModelProvider.Factory {...}:

WordViewModelFactory是一個用於創建WordViewModel實例的工廠類。
它實現了ViewModelProvider.Factory介面,並重寫了create方法。
在create方法中,它首先檢查所請求的ViewModel類是否是WordViewModel,如果是,則返回一個新的WordViewModel實例,否則拋出一個IllegalArgumentException異常。
這些類的組合使得在應用程式中可以方便地管理與單詞相關的UI邏輯和數據。ViewModel類負責從數據層獲取數據,併在需要時將其提供給UI層。ViewModelFactory類負責實例化ViewModel類,並確保每個ViewModel都具有正確的依賴項。

 

6.創建Adapter

創建一個RecyclerView的適配器類(WordListAdapter),用於將數據綁定到RecyclerView中的列表項。

 1 import android.view.LayoutInflater
 2 import android.view.View
 3 import android.view.ViewGroup
 4 import android.widget.TextView
 5 import androidx.recyclerview.widget.DiffUtil
 6 import androidx.recyclerview.widget.ListAdapter
 7 import androidx.recyclerview.widget.RecyclerView
 8 import com.example.roomwordsample.R
 9 import com.example.roomwordsample.datac.Word
10 
11 class WordListAdapter : ListAdapter<Word, WordListAdapter.WordViewHolder>(WordsComparator()) {
12     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WordViewHolder {
13         return WordViewHolder.create(parent)
14     }
15 
16     override fun onBindViewHolder(holder: WordViewHolder, position: Int) {
17         val current = getItem(position)
18         holder.bind(current.word)
19     }
20     class WordViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
21         private val wordItemView: TextView = itemView.findViewById(R.id.textView)
22 
23         fun bind(text: String?) {
24             wordItemView.text = text
25         }
26 
27         companion object {
28             fun create(parent: ViewGroup): WordViewHolder {
29                 val view: View = LayoutInflater.from(parent.context)
30                     .inflate(R.layout.recyclerview_item, parent, false)
31                 return WordViewHolder(view)
32             }
33         }
34     }
35 
36     class WordsComparator : DiffUtil.ItemCallback<Word>() {
37         override fun areItemsTheSame(oldItem: Word, newItem: Word): Boolean {
38             return oldItem === newItem
39         }
40 
41         override fun areContentsTheSame(oldItem: Word, newItem: Word): Boolean {
42             return oldItem.word == newItem.word
43         }
44     }
45 }

class WordListAdapter : ListAdapter<Word, WordListAdapter.WordViewHolder>(WordsComparator()) {...}:

WordListAdapter繼承自ListAdapter類,並指定了泛型參數,第一個參數是數據項的類型(Word),第二個參數是ViewHolder的類型(WordViewHolder),並傳入了一個用於比較數據項的WordsComparator對象。
ListAdapter是RecyclerView的一個輔助類,用於處理列表數據的更新和差異計算。
onCreateViewHolder:

onCreateViewHolder方法用於創建ViewHolder對象。在這裡,它調用了WordViewHolder的create方法來創建ViewHolder。
onBindViewHolder:

onBindViewHolder方法用於綁定數據到ViewHolder上。在這裡,它獲取當前位置的數據項,然後調用ViewHolder的bind方法將數據綁定到UI上。
class WordViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {...}:

WordViewHolder是一個內部類,繼承自RecyclerView.ViewHolder類,用於管理列表項的視圖。
它包含一個私有屬性wordItemView,類型為TextView,用於顯示單詞。
bind方法:

bind方法用於將數據綁定到ViewHolder上。在這裡,它接收一個字元串參數,並將其設置到wordItemView的文本屬性上。
create方法:

create方法用於創建ViewHolder實例。在這裡,它使用LayoutInflater從指定的佈局文件(recyclerview_item.xml)中創建一個View對象,並將其傳遞給ViewHolder的構造函數。
WordsComparator類:

WordsComparator是一個內部類,繼承自DiffUtil.ItemCallback<Word>類,用於比較兩個數據項。
areItemsTheSame方法用於判斷兩個數據項是否代表同一個對象。
areContentsTheSame方法用於判斷兩個數據項的內容是否相同。
這個適配器類負責管理RecyclerView的列表項,包括創建ViewHolder、綁定數據以及比較數據項的差異。

7.創建MainActivity

 1 import android.app.Activity
 2 import android.content.Intent
 3 import android.os.Bundle
 4 import android.widget.Toast
 5 import androidx.activity.viewModels
 6 import androidx.appcompat.app.AppCompatActivity
 7 import androidx.lifecycle.Observer
 8 import androidx.recyclerview.widget.LinearLayoutManager
 9 import androidx.recyclerview.widget.RecyclerView
10 import com.example.roomwordsample.adapter.WordListAdapter
11 import com.example.roomwordsample.datac.Word
12 import com.example.roomwordsample.vm.WordViewModel
13 import com.example.roomwordsample.vm.WordViewModelFactory
14 import com.google.android.material.floatingactionbutton.FloatingActionButton
15 
16 
17 class MainActivity : AppCompatActivity() {
18     private val newWordActivityRequestCode = 1
19 
20     private val wordViewModel: WordViewModel by viewModels {
21         WordViewModelFactory((application as WordsApplication).repository)
22     }
23 
24     override fun onCreate(savedInstanceState: Bundle?) {
25         super.onCreate(savedInstanceState)
26         setContentView(R.layout.activity_main)
27         val recyclerView = findViewById<RecyclerView>(R.id.recyclerview)
28         val adapter = WordListAdapter()
29         recyclerView.adapter = adapter
30         recyclerView.layoutManager = LinearLayoutManager(this)
31         wordViewModel.allWords.observe(this, Observer { words ->
32             words?.let { adapter.submitList(it) }
33         })
34         val fab = findViewById<FloatingActionButton>(R.id.fab)
35         fab.setOnClickListener {
36             val intent = Intent(this@MainActivity, NewWordActivity::class.java)
37             startActivityForResult(intent, newWordActivityRequestCode)
38         }
39     }
40     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
41         super.onActivityResult(requestCode, resultCode, data)
42 
43         if (requestCode == newWordActivityRequestCode && resultCode == Activity.RESULT_OK) {
44             data?.getStringExtra(NewWordActivity.EXTRA_REPLY)?.let {
45                 val word = Word(it)
46                 wordViewModel.insert(word)
47             }
48         } else {
49             Toast.makeText(
50                 applicationContext,
51                 R.string.empty_not_saved,
52                 Toast.LENGTH_LONG).show()
53         }
54     }
55 }

 

8.創建NewWordActivity

 1 import android.app.Activity
 2 import android.content.Intent
 3 import android.os.Bundle
 4 import android.text.TextUtils
 5 import android.widget.Button
 6 import android.widget.EditText
 7 import androidx.appcompat.app.AppCompatActivity
 8 
 9 class NewWordActivity : AppCompatActivity() {
10     private lateinit var editWordView:EditText
11 
12     override fun onCreate(savedInstanceState: Bundle?) {
13         super.onCreate(savedInstanceState)
14         setContentView(R.layout.activity_new_word)
15         editWordView = findViewById(R.id.edit_word)
16         val button = findViewById<Button>(R.id.button_save)
17         button.setOnClickListener {
18             val replyIntent = Intent()
19             if (TextUtils.isEmpty(editWordView.text)) {
20                 setResult(Activity.RESULT_CANCELED, replyIntent)
21             } else {
22                 val word = editWordView.text.toString()
23                 replyIntent.putExtra(EXTRA_REPLY, word)
24                 setResult(Activity.RESULT_OK, replyIntent)
25             }
26             finish()
27         }
28     }
29     companion object{
30         const val EXTRA_REPLY = "com.example.android.wordlistsql.REPLY"
31     }
32 }

 

9.創建WordsApplication

創建一個名為WordsApplication的自定義Application類,用於初始化應用程式的全局狀態。

 1 import android.app.Application
 2 import com.example.roomwordsample.repository.WordRepository
 3 import com.example.roomwordsample.room.WordRoomDatabase
 4 import kotlinx.coroutines.CoroutineScope
 5 import kotlinx.coroutines.SupervisorJob
 6 
 7 class WordsApplication:Application() {
 8     val applicationScope = CoroutineScope(SupervisorJob())
 9     val database by lazy { WordRoomDatabase.getDatabase(this,applicationScope) }
10     val repository by lazy { WordRepository(database.wordDao()) }
11 }

class WordsApplication : Application() {...}:

WordsApplication類繼承自Android的Application類,表示一個應用程式級別的全局狀態。
val applicationScope = CoroutineScope(SupervisorJob()):

applicationScope是一個CoroutineScope對象,用於管理應用程式範圍內的協程。它使用了SupervisorJob,表示在子協程出現異常時,不會影響其他子協程的執行。
val database by lazy { WordRoomDatabase.getDatabase(this, applicationScope) }:

database是一個延遲初始化的屬性,使用了懶載入機制。它通過調用WordRoomDatabase.getDatabase()方法來獲取應用程式的資料庫實例。這個資料庫實例是單例的,並且會在第一次訪問時被初始化。
val repository by lazy { WordRepository(database.wordDao()) }:

repository也是一個延遲初始化的屬性,使用了懶載入機制。它通過調用WordRepository類的構造函數來創建一個單詞倉庫的實例。這個倉庫實例會將資料庫實例傳遞給其構造函數,以便它可以與資料庫進行交互。
WordsApplication類負責創建應用程式的全局狀態,包括資料庫實例和單詞倉庫實例。這些實例可以在應用程式的任何地方使用,以便進行數據存儲和檢索操作。

 

查看room資料庫文件

room資料庫本質上就是對SQlite的一個封裝,類似於java中的mybatis框架,對SQLiteOpenHelper類進行了一些封裝,簡化了資料庫的操作。

簡單來說:Room是一個基於SQLite的強大資料庫框架。

在AndroidManifest.xml清單文件中添加許可權

1     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

導出並使用SQLiteStudio軟體打開,其他資料庫管理工具也可以

SQLiteStudio下載鏈接:https://sqlitestudio.pl/

 在AndroidStudio中打開Device Explorer(設備瀏覽器)

 文件尾碼為.db或.sqlite都可以,這裡我直接將三個文件(二進位文件)導出

使用SQLite打開界面

 

 

本篇關於Android中使用Room數據的文章到這就結束了~

感謝觀看~~喜歡的小伙伴一鍵三連,後續可能會更新其他文章

參考其他鏈接:

Android的room資料庫使用小結(kotlin):https://cloud.tencent.com/developer/article/1831046

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 插入數據 1.1 insert 如果我們需要一次性往資料庫表中插入多條記錄,可以從以下三個方面進行優化。 insert into tb_test values(1,'tom'); insert into tb_test values(2,'cat'); insert into tb_test ...
  • 剛進公司,任務是接管PLM系統,但是還在給外包團隊開發,沒有代碼。無妨先看業務和資料庫,ok,業務看不懂,只能先看資料庫,資料庫沒有數據字典,這個系統沒有任何文檔產出......練手時發現資料庫類型是Oracle,面對百度不成問題,數據字典只能看前端然後去資料庫裡面一個個找著對應自己整理了,純折磨 ...
  • 引言 在數據驅動的世界中,企業正在尋求可靠且高性能的解決方案來管理其不斷增長的數據需求。本系列博客從一個重視數據安全和合規性的 B2C 金融科技客戶的角度來討論雲上雲下混合部署的情況下如何利用亞馬遜雲科技雲原生服務、開源社區產品以及第三方工具構建無伺服器數據倉庫的解耦方法。 Apache Dolph ...
  • 之前寫過一篇文章MySQL如何獲取binlog的開始時間和結束時間[1],文章裡面介紹瞭如何獲取MySQL資料庫二進位日誌(binlog)的開始時間與結束時間的一些方法。實際應用當中,我們可能還會遇到效率/性能方面的問題。最近對這個問題做了一些研究,這裡就介紹一下如何快速獲取MySQL二進位日誌(b ...
  • 本文分享自華為雲社區《GaussDB(DWS)行執行引擎詳解》,作者:yd_227398895。 1.前言 GaussDB(DWS)包含三大引擎,一是SQL執行引擎,用來解析用戶輸入的SQL語句,生成執行計劃,供執行引擎來執行;二是執行引擎,其中包含了行執行引擎和列執行引擎,執行引擎即查詢的執行者, ...
  • 一、Stage模型概述和組件 1.Stage模型概述 HarmonyOS的Stage模型是其應用程式的核心概念之一,它提供了一種靈活的方式來管理應用程式的生命周期和界面管理。 Stage模型由以下幾個主要組件組成: 應用程式:每個應用程式被視為一個Stage,它可以包含一個或多個視窗,每個窗 ...
  • 一、組合手勢 應用程式的手勢操作是指在移動設備上使用手指或手勢進行與應用程式交互的方式。手勢操作可以包括點擊、滑動、雙擊、捏合等動作,用於實現不同的功能和操作。 HarmonyOS中常見的手勢操作及其功能: 組合手勢是由多個手勢組合而成的手勢動作。通過不同手勢的組合,可以完成更複雜的操作。例如, ...
  • 為了做《基於安卓定位的考勤系統》,學了一些雜亂的知識,在這裡簡單記錄一下。除了在C#桌面應用開發中感性的體會到了些XML佈局的知識以及課上學習的Java知識,其他也算是零基礎了。 Google Android Developer的課程 2023/10/25 :跟著官方文檔先快速入門一下基本內容。截至 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 微服務架構已經成為搭建高效、可擴展系統的關鍵技術之一,然而,現有許多微服務框架往往過於複雜,使得我們普通開發者難以快速上手並體驗到微服務帶了的便利。為瞭解決這一問題,於是作者精心打造了一款最接地氣的 .NET 微服務框架,幫助我們輕鬆構建和管理微服務應用。 本框架不僅支持 Consul 服務註 ...
  • 先看一下效果吧: 如果不會寫動畫或者懶得寫動畫,就直接交給Blend來做吧; 其實Blend操作起來很簡單,有點類似於在操作PS,我們只需要設置關鍵幀,滑鼠點來點去就可以了,Blend會自動幫我們生成我們想要的動畫效果. 第一步:要創建一個空的WPF項目 第二步:右鍵我們的項目,在最下方有一個,在B ...
  • Prism:框架介紹與安裝 什麼是Prism? Prism是一個用於在 WPF、Xamarin Form、Uno 平臺和 WinUI 中構建鬆散耦合、可維護和可測試的 XAML 應用程式框架 Github https://github.com/PrismLibrary/Prism NuGet htt ...
  • 在WPF中,屏幕上的所有內容,都是通過畫筆(Brush)畫上去的。如按鈕的背景色,邊框,文本框的前景和形狀填充。藉助畫筆,可以繪製頁面上的所有UI對象。不同畫筆具有不同類型的輸出( 如:某些畫筆使用純色繪製區域,其他畫筆使用漸變、圖案、圖像或繪圖)。 ...
  • 前言 嗨,大家好!推薦一個基於 .NET 8 的高併發微服務電商系統,涵蓋了商品、訂單、會員、服務、財務等50多種實用功能。 項目不僅使用了 .NET 8 的最新特性,還集成了AutoFac、DotLiquid、HangFire、Nlog、Jwt、LayUIAdmin、SqlSugar、MySQL、 ...
  • 本文主要介紹攝像頭(相機)如何採集數據,用於類似攝像頭本地顯示軟體,以及流媒體數據傳輸場景如傳屏、視訊會議等。 攝像頭採集有多種方案,如AForge.NET、WPFMediaKit、OpenCvSharp、EmguCv、DirectShow.NET、MediaCaptre(UWP),網上一些文章以及 ...
  • 前言 Seal-Report 是一款.NET 開源報表工具,擁有 1.4K Star。它提供了一個完整的框架,使用 C# 編寫,最新的版本採用的是 .NET 8.0 。 它能夠高效地從各種資料庫或 NoSQL 數據源生成日常報表,並支持執行複雜的報表任務。 其簡單易用的安裝過程和直觀的設計界面,我們 ...
  • 背景需求: 系統需要對接到XXX官方的API,但因此官方對接以及管理都十分嚴格。而本人部門的系統中包含諸多子系統,系統間為了穩定,程式間多數固定Token+特殊驗證進行調用,且後期還要提供給其他兄弟部門系統共同調用。 原則上:每套系統都必須單獨接入到官方,但官方的接入複雜,還要官方指定機構認證的證書 ...
  • 本文介紹下電腦設備關機的情況下如何通過網路喚醒設備,之前電源S狀態 電腦Power電源狀態- 唐宋元明清2188 - 博客園 (cnblogs.com) 有介紹過遠程喚醒設備,後面這倆天瞭解多了點所以單獨加個隨筆 設備關機的情況下,使用網路喚醒的前提條件: 1. 被喚醒設備需要支持這WakeOnL ...
  • 前言 大家好,推薦一個.NET 8.0 為核心,結合前端 Vue 框架,實現了前後端完全分離的設計理念。它不僅提供了強大的基礎功能支持,如許可權管理、代碼生成器等,還通過採用主流技術和最佳實踐,顯著降低了開發難度,加快了項目交付速度。 如果你需要一個高效的開發解決方案,本框架能幫助大家輕鬆應對挑戰,實 ...