- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
简介:
还在使用原生的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 。
这个链接可能需要神奇的力量,也可以使用梯子打开新世界的大门~ 。
架构组件:
。
依赖添加:
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" }
ext { roomVersion = '2.1.0-alpha06' //... 省略无关 }
项目结构:
。
使用步骤:
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(): 这是一个抽象方法,用于执行删除操作.
这个接口定义了三种操作:获取按字母顺序排列的单词列表、插入单词到数据库中以及删除数据库中所有的单词.
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 。
。
。
。
最后此篇关于android中Room数据库的基本使用的文章就讲到这里了,如果你想了解更多关于android中Room数据库的基本使用的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
即使从 androidx.room.Room 导入,Room.databaseBuilder() 也无法找到 Room 依赖项。 我为数据库制作了一个不同的 Kotlin 库,并在 Room 的 gr
我正在尝试迁移我们的项目以使用 Room,顺便说一句,我认为这是向前迈出的一大步。 我有以下结构: public class Entity extends BaseObservable { @
Here是房间数据库的官方文档。它包含以下代码 val db = Room.databaseBuilder( applicationContext, A
Here是房间数据库的官方文档。它包含以下代码 val db = Room.databaseBuilder( applicationContext, A
我有一张供用户使用的表。用户创建一个类别,然后将 Youtube 视频分配到该类别。我目前有一个用户表、类别表(用户 ID 外键)和 youtubevideo 表(用户 ID 外键、类别外键)。 我目
拥有三张 table 的 Android Room timestamp , index , details ,并且这三个都有 @PrimaryKey @ColumnInfo(name = "id")
让我们举一个基本的例子 用于存储用户的表 @Entity (tableName="users") class UsersEntity( @PrimaryKey val id var
想确认是否可以将实体 bean 绑定(bind)到表的部分列? 例子: 表“A”有列 id, col1, col2, col3, col4, col5, ... , col10 但是我只需要 id、c
问题 双向数据绑定(bind)允许您使用来自对象的数据自动填充 UI 组件,然后在用户编辑这些 UI 组件时自动更新对象。 当用户编辑 UI 组件时,有没有办法不仅自动更新内存中的对象,而且自动更新/
我在 Android Room 中使用可观察查询来触发更新,最终在底层数据发生变化时改变 UI。 有时这些查询涉及多个表,有时用户执行将新值插入到这些表中的操作。插入通常一个接一个地快速完成(即在不到
我想知道点击新房间后如何离开房间 我的页面是这样的。 左侧列表来自MySQL服务器,它获取我的聊天列表。每个房间名称都有 id 值,即房间名称。并且它还有onclick函数可以在客户端使用函数。 当我
我正在尝试将此模块化项目升级到最新的依赖项,但 gradle 构建失败并显示 could not resolve androidx.room:room-runtime:2.4.2我已经包含了maven
在使用 Kotlin Coroutines Flow、Room 和 Live Data 时,我面临着一个非常奇怪的行为。每当我关闭我的设备大约 5-10 秒然后重新打开它时,协程流程就会重新运行而没有
我正在与一位同事讨论我们部署的一款软件遇到的问题,他提到这与一段时间内预订房间的概念问题有何相似之处,算法应该输出房间需要最少开关的预订(因此,例如,最佳解决方案可能是在一个房间停留 3 天,其余时间
如何使用 Room Persistence 库“创建触发器” CREATE TRIGGER IF NOT EXISTS delete_till_10 INSERT ON user WHEN (sel
你如何在 Android Room 中使用 List 的 我有一个表实体,我想通过 Android Room 将其保存在我的 SQLDatabase 中。我已经按照我在网上可以做得很好的一切,并且没有
我正在研究可以在图像上绘制矩形的东西。它工作得很好,因为 JavaFX 很容易,但我遇到了一个我似乎不理解的小问题。 我一直使用 for (object b : ArrayList) ,但从未发生过这
我对java完全陌生。我花了几个小时寻找这个问题的解决方案,但每个答案都涉及传递参数或使用 void,但在这种情况下我不会这样做。 我有两个 java 文件,一个用于 Room 类,一个用于 Tour
我正在创建一个聊天网站,我正在使用 Strophe.js 和 Strophe.muc.js 插件。单人聊天功能运行良好,但我也不想实现群聊功能,用户可以在其中创建房间并邀请其他用户加入他们的房间。使用
按照教程设置 Room 持久性库时,我在 Android 设备上进行测试时遇到了这个错误。 java.lang.RuntimeException:找不到 PackageName.AppDatabase
我是一名优秀的程序员,十分优秀!