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 MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...