简介:

还在使用原生的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

android中Room数据库的基本使用的更多相关文章

  1. android中的数据库操作

    如何在android中调用数据库资源 在android中主要有两种方法来实现对数据库的访问,一种是adb shell方式,另一种是通过相关的android 的java类来间接的对数据库来进行操作.其中 ...

  2. android中的数据库操作(转)

    android中的数据库操作 android中的应用开发很难避免不去使用数据库,这次就和大家聊聊android中的数据库操作. 一.android内的数据库的基础知识介绍 1.用了什么数据库   an ...

  3. android中的数据库操作(SQLite)

    android中的数据库操作 android中的应用开发很难避免不去使用数据库,这次就和大家聊聊android中的数据库操作. 一.android内的数据库的基础知识介绍 1.用了什么数据库   an ...

  4. 使用adb命令查看android中的数据库

    在采用数据库操作时,经常会出现查询或删除等操作语句执行失败,但是有找不到具体原因.下面将介绍一种命令行方式进行数据库操作,来验证android中的数据库操作语句是否正确等. 具体操作步骤如下: (1) ...

  5. Android中SQLite数据库操作(1)——使用SQL语句操作SQLite数据库

    下面是最原始的方法,用SQL语句操作数据库.后面的"Android中SQLite数据库操作(2)--SQLiteOpenHelper类"将介绍一种常用的android封装操作SQL ...

  6. Android中SQLite数据库小计

    2016-03-16 Android数据库支持 本文节选并翻译<Enterprise Android - Programing Android Database Applications for ...

  7. 我的Android六章:Android中SQLite数据库操作

    今天学习的内容是Android中的SQLite数据库操作,在讲解这个内容之前小编在前面有一篇博客也是讲解了SQLite数据库的操作,而那篇博客的讲解是讲述了 如何在Window中通过DOM来操作数据库 ...

  8. Android中Sqlite数据库多线程并发问题

    最近在做一个Android项目, 为了改善用户体验,把原先必须让用户“等待”的过程改成在新线程中异步执行.但是这样做遇到了多个线程同时需要写Sqlite数据库,导致操作数据库失败. 本人对Java并不 ...

  9. android中sqlite数据库的基本使用和添加多张表

    看了很多关于android使用sqlite数据库的文章,很多都是介绍了数据库的建立和表的建立,而表通常都是只建立一张,而实际情况我们用到的表可能不止一张,那这种情况下我们又该怎么办呢,好了,下面我教大 ...

  10. Android中当数据库需要更新时我们该怎么办?

    问题:Android数据库更新并保留原来的数据如何实现 Andoird的SQLiteOpenHelper类中有一个onUpgrade方法.帮助文档中只是说当数据库升级时该方法被触发.经过实践,解决了我 ...

随机推荐

  1. #分治,决策单调性dp#CF868F Yet Another Minimization Problem

    题目 给定一个序列 \(a\),要把它分成 \(k\) 个子段.(\(n\leq 10^5,k\leq 20\)) 每个子段的费用是其中相同元素的对数.求所有子段的费用之和的最小值. 分析 有一个很明 ...

  2. OpenAtom OpenHarmony分论坛,今天14:00见!附大事记精彩发布

    2022开放原子全球开源峰会 OpenAtom OpenHarmony分论坛 万物互联,使能千行百业 整装待发!精彩今日揭晓与您相约7月27日 14:00  

  3. [P4551] 最长异或路径 题解

    过程 手写利用DFS求出每个点到根节点的异或距离 不难得出 xor_dis[x][y]=xor_dis[0][x]^xor_dis[0][y] 于是树上异或问题转换成了Trie上异或问题. 代码 直接 ...

  4. RabbitMQ 10 头部模式

    头部模式是根据头部信息来决定的,在发送的消息中是可以携带一些头部信息的(类似于HTTP),可以根据这些头部信息来决定路由到哪一个消息队列中. 定义配置类. import org.springframe ...

  5. openGauss Sqlines 使用指导

    openGauss Sqlines 使用指导 Sqlines 简介 Sqlines 是一款开源软件,支持多种数据库之间的 SQL 语句语法的的转换,openGauss 将此工具修改适配,新增了 ope ...

  6. HarmonyOS线上Codelabs系列挑战赛第二期:调用三方库,制作酷炫的视觉效果

      HarmonyOS线上Codelabs系列挑战赛正如火如荼进行中,开发者们可以通过体验基于HarmonyOS特性和能力的应用开发,快速构建有趣.有用的应用程序.火速加入,与众多开发者一起碰撞想法, ...

  7. mysql 重新整理——性能下降的原因[四]

    前言 什么是性能下降? 其实就是代码运行的环境变了,那么环境变化是什么? 比如cpu上升了,内存满了.有或者表中数量增加了,量变了. 其实这些是dba干的,但是呢,我们也需要去了解下,并且优化我们的c ...

  8. 分享一款嵌入式开源按键框架代码工程MultiButton

    一.工程简介 MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块. Github地址:https://github.com/0x1abin/MultiButton 这个项目非常精简,只 ...

  9. uni-app上传图片和文件

    如图所示: 上传图片,使用的是uni.chooseImage这个官方api,count 数量根据自己的需求来,我们是最多只能上传9张 uploadImgEvent(){ uni.chooseImage ...

  10. css添加属性,让浏览器检查无法选中元素

    1.表现 浏览器直接选中元素的时候,仅能直接选中整个body,想要找到具体元素,需要自己手动寻找,没太大实际作用,仅仅让不懂的人不能简简单单的直接定位元素然后修改里面的内容 pointer-event ...