【问题标题】:Android-Kotlin preload a Room DatabaseAndroid-Kotlin 预加载房间数据库
【发布时间】:2021-02-11 18:43:24
【问题描述】:

我正在使用 Kotlin。我对 Java、Kotlin 和 Android 了解不多。我有两个表,Item 和 ItemOrderDetails。

我项目中的主要文件有:ItemDatabase、ItemDao、ItemOrderDetailsDao、Item、ItemOrderDetails、ItemRepository和ItemViewModel。

  1. 实体(Item & ItemOrderDetails)。
  2. DAO (ItemDao & ItemOrderDetailsDao)。
  3. 数据库(ItemDatabase)。
  4. 存储库 (ItemRepository)。
  5. ViewModel (ItemViewModel)。

首先需要检查数据是否存在。它应该像这样工作:

如果不存在数据,则预加载两个表中的所有数据。

如果表中已经存在数据,则更新数据,即将要预加载的数据和已经存在的数据合并。如果在这种情况下存在相同数据的副本,则覆盖数据。

请告诉我如何更改 ItemDatabase.kt,以实现这一点。

日志

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.itemapp, PID: 24878
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.itemapp/com.example.itemapp.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.itemapp.viewmodel.ItemViewModel
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2895)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1616)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:176)
        at android.app.ActivityThread.main(ActivityThread.java:6651)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)
     Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.itemapp.viewmodel.ItemViewModel
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:275)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:106)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
        at com.example.itemapp.fragments.list.ListFragment.onCreateView(ListFragment.kt:43)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2699)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1199)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1368)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1446)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1509)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2637)
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2589)
        at androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2723)
        at androidx.fragment.app.FragmentStateManager.activityCreated(FragmentStateManager.java:346)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1200)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1368)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1446)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1509)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2637)
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2589)
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:247)
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:541)
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:210)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1335)
        at android.app.Activity.performStart(Activity.java:7108)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2780)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2895) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1616) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:176) 
        at android.app.ActivityThread.main(ActivityThread.java:6651) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824) 
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:334)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:106) 
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185) 
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) 
        at com.example.itemapp.fragments.list.ListFragment.onCreateView(ListFragment.kt:43) 
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2699) 
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320) 
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1199) 
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1368) 
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1446) 
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1509) 
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2637) 
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2589) 
        at androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2723) 
        at androidx.fragment.app.FragmentStateManager.activityCreated(FragmentStateManager.java:346) 
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1200) 
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1368) 
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1446) 
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1509) 
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2637) 
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2589) 
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:247) 
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:541) 
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:210) 
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1335) 
        at android.app.Activity.performStart(Activity.java:7108) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2780) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2895) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1616) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:176) 
        at android.app.ActivityThread.main(ActivityThread.java:6651) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824) 
     Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
        at androidx.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:267)
        at androidx.room.RoomDatabase.query(RoomDatabase.java:323)
        at androidx.room.util.DBUtil.query(DBUtil.java:83)
        at com.example.itemapp.data.ItemOrderDetailsDao_Impl.getAllItems(ItemOrderDetailsDao_Impl.java:109)
        at com.example.itemapp.repository.ItemRepository.<init>(ItemRepository.kt:15)
        at com.example.itemapp.viewmodel.ItemViewModel.<init>(ItemViewModel.kt:24)
            ... 38 more

ListFragment.kt

class ListFragment : Fragment(), RecyclerView_1_Adapter.OnItemClickListener1 {

    private lateinit var mItemViewModel: ItemViewModel
    private lateinit var nItemViewModel: ItemViewModel
    var itemList = mutableListOf<Item>()
    mItemViewModel.addItems(DataFragment.item_data)   // Error: Expecting member declaration.

    private lateinit var recyclerView1_adapter: RecyclerView_1_Adapter
    lateinit var recyclerView1 : RecyclerView

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_list, container, false)

        recyclerView1_adapter = RecyclerView_1_Adapter(itemList, this)
        recyclerView1 = view.recyclerview1
        recyclerView1.layoutManager = LinearLayoutManager(requireContext())
        recyclerView1.adapter = recyclerView1_adapter

        // ItemViewModel
        mItemViewModel = ViewModelProvider(this).get(ItemViewModel::class.java)
        nItemViewModel.addItems(DataFragment.item_data)
        nItemViewModel.insertItems(DataFragment.item_order_details_data)

        mItemViewModel.readAllData.observe(viewLifecycleOwner, Observer { item ->
            recyclerView1_adapter.setData(item)
        })
               
        return view
    }
          
}

RecyclerView_1_Adapter.kt

class RecyclerView_1_Adapter (
    var itemList: MutableList<Item>, // = mutableListOf<Item>()
    val listener1: OnItemClickListener1
) : RecyclerView.Adapter<RecyclerView_1_Adapter.RecyclerView_1_DataViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView_1_DataViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.recyview1_row, parent, false)
        return RecyclerView_1_DataViewHolder(view)
    }

    override fun getItemCount(): Int {
        return itemList.size
    }

    override fun onBindViewHolder(holder: RecyclerView_1_DataViewHolder, position: Int) {
        val currentItem = itemList[position]
        holder.itemView.apply {
            firstName_list.text = currentItem.firstName
            lastName_list.text = currentItem.lastName
        }
    }

    inner class RecyclerView_1_DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
        View.OnClickListener {

        init {
            itemView.setOnClickListener(this)
        }

        override fun onClick(v: View?) {
            val position = adapterPosition
            val currentItem2 = itemList[position]
            if (position != RecyclerView.NO_POSITION) {
                listener1.onItemClick1(position, currentItem2)
            }
        }
    }

    interface OnItemClickListener1 {
        fun onItemClick1(position: Int, currentItem1: Item)
    }

    fun setData(item: MutableList<Item>){
        this.itemList = item
        notifyDataSetChanged()
    }

}

ItemDao.kt(更新)

@Dao
interface ItemDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun addItem(item: Item)
//    suspend fun insertItems(item: Item)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun addItems(items: List<Item>)

    @Update
    suspend fun updateItem(item: Item)

    @Delete
    suspend fun deleteItem(item: Item)

    @Query("DELETE FROM item_table")
    suspend fun deleteAllItems()

    @Query("SELECT * FROM item_table ORDER BY id ASC")
    fun readAllData(): LiveData<MutableList<Item>>

}

ItemOrderDetailsDao.kt(更新)

@Dao
interface ItemOrderDetailsDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertItem(items: ItemOrderDetails)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertItems(item: List<ItemOrderDetails>)

    @Query("SELECT * FROM item_order_details_table ORDER BY id ASC")
    fun getAllItems(): MutableList<ItemOrderDetails>

}

ItemRepository.kt(更新)

class ItemRepository(
    private val itemDao: ItemDao,
    private val itemOrderDetailsDao: ItemOrderDetailsDao
) {

    val readAllData: LiveData<MutableList<Item>> = itemDao.readAllData()
    val getAllItems: MutableList<ItemOrderDetails> = itemOrderDetailsDao.getAllItems()
    /*suspend fun readAllData(user: Item){
        itemDao.readAllData(LiveData<List<Item>>)
    }*/

    suspend fun addItem(item: Item){
        itemDao.addItem(item)
    }

    suspend fun insertItem(item: ItemOrderDetails) {
        itemOrderDetailsDao.insertItem(item)
    }

    suspend fun addItems(items: List<Item>){
        itemDao.addItems(items)
    }

    suspend fun insertItems(items: List<ItemOrderDetails>){
        itemOrderDetailsDao.insertItems(items)
    }

    suspend fun updateItem(item: Item){
        itemDao.updateItem(item)
    }

    suspend fun deleteItem(item: Item){
        itemDao.deleteItem(item)
    }

    suspend fun deleteAllItems(){
        itemDao.deleteAllItems()
    }

}

ItemViewModel.kt(更新)

class ItemViewModel(application: Application): AndroidViewModel(application) {

    val readAllData: LiveData<MutableList<Item>>
    val getAllItems: MutableList<ItemOrderDetails>
    private val repository: ItemRepository

    init {
        val itemDao = App.db.itemDao()
        val itemOrderDetailsDao = App.db.itemOrderDetailsDao()
//        val itemDao = ItemDatabase.getDatabase(application).userDao()

        repository = ItemRepository(itemDao, itemOrderDetailsDao)
        readAllData = repository.readAllData
        getAllItems = repository.getAllItems
    }

    fun addItem(item: Item){
        viewModelScope.launch(Dispatchers.IO) {
            repository.addItem(item)
        }
    }

    fun insertItem(item: ItemOrderDetails) {
        viewModelScope.launch(Dispatchers.IO) {
            repository.insertItem(item)
        }
    }

    fun addItems(items: List<Item>){
        viewModelScope.launch(Dispatchers.IO) {
            repository.addItems(items)
        }
    }

    fun insertItems(items: List<ItemOrderDetails>){
        viewModelScope.launch(Dispatchers.IO) {
            repository.insertItems(items)
        }
    }

    fun updateItem(item: Item){
        viewModelScope.launch(Dispatchers.IO) {
            repository.updateItem(item)
        }
    }

    fun deleteItem(item: Item){
        viewModelScope.launch(Dispatchers.IO) {
            repository.deleteItem(item)
        }
    }

    fun deleteAllItems(){
        viewModelScope.launch(Dispatchers.IO) {
            repository.deleteAllItems()
        }
    }
    
    App.db.itemDao().addItemsFromFragment(DataFragment.item_data)   // Expecting member declaration
    App.db.itemOrderDetailsDao().insertItemsFromFragment(DataFragment.item_order_details_data)  // Expecting member declaration
   
}

DataFragment.kt(更新)

class DataFragment {

    companion object Data{
        var item_order : Int = 0
        var item_order_alert : Int = 0
        var selectedItems1 = arrayOf<Int>(0)

        var item_details_list = mutableListOf<ItemDetails>()
        
        val item_data = listOf(
            Item(0, "first_name_1", "last_name_1", "item_value_a_1"),
            Item(0, "first_name_2", "last_name_2", "item_value_a_2"),
            Item(0, "first_name_3", "last_name_3", "item_value_a_3")
        )

        val item_order_details_data = listOf(
            ItemOrderDetails(0, "item_group_1", "item_name_1", "item-value_b_1", "item_base_1", "item_up_1"),
            ItemOrderDetails(0, "item_group_2", "item_name_2", "item-value_b_2", "item_base_2", "item_up_2"),
            ItemOrderDetails(0, "item_group_3", "item_name_3", "item-value_b_3", "item_base_3", "item_up_3")
        )

        fun addItemsFromFragment(items: List<Item>){
            viewModel.addItems(items)
        }

        fun insertItemsFromFragment(items: List<ItemOrderDetails>){
            viewModel.insertItems(items)
        }

    }

}

MainActivity.kt(更新)

package com.example.itemapp

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.setupActionBarWithNavController
import com.example.itemapp.data.App
import com.example.itemapp.fragments.add.DataFragment

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        setupActionBarWithNavController(findNavController(R.id.fragment))

        App.db.itemDao().addItemsFromFragment(DataFragment.item_data)
        App.db.itemOrderDetailsDao().insertItemsFromFragment(DataFragment.item_order_details_data)
        // Error - Unresolved reference: addItemsFromFragment
        // Error - Unresolved reference: insertItemsFromFragment        
    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.fragment)
        return navController.navigateUp() || super.onSupportNavigateUp()
    }
}

ItemDatabase.kt(更新)

package com.example.itemapp.data

import androidx.room.Database
import androidx.room.RoomDatabase
import com.example.itemapp.model.Item
import com.example.itemapp.model.ItemOrderDetails

@Database(
    entities = [
        Item::class,
        ItemOrderDetails::class
    ], version = 1, exportSchema = false)
abstract class ItemDatabase : RoomDatabase() {

//    abstract fun userDao(): ItemDao

    abstract fun getItemDao(): ItemDao
    abstract fun getItemDetailsDao(): ItemOrderDetailsDao

        /*companion object {
            @Volatile
            private var INSTANCE: ItemDatabase? = null

            fun getDatabase(context: Context): ItemDatabase {
                val tempInstance = INSTANCE
                if (tempInstance != null) {
                    return tempInstance
                }
                synchronized(this) {
                    val instance = Room.databaseBuilder(
                        context.applicationContext,
                        ItemDatabase::class.java,
                        "item_database"
                    ).build()
                    INSTANCE = instance
                    return instance
                }
            }
        }*/
}

DbRepository.kt(更新)

package com.example.itemapp.data

import android.content.Context
import androidx.room.Room

    // Adding a new class to access DB.
class DbRepository (private val database: ItemDatabase) {

    companion object {
        private var instance: DbRepository? = null

        fun getInstance(context: Context): DbRepository {
            return instance ?: synchronized(this) {
                instance ?: DbRepository(initializeDb(context)).also { instance = it }
            }
        }

        private fun initializeDb(context: Context): ItemDatabase {
            return Room.databaseBuilder(
                context,
                ItemDatabase::class.java, "ItemDb"
            ).build()
        }
    }

    fun itemDao():ItemDao = database. getItemDao()

    fun itemDetailsDao():ItemOrderDetailsDao = database.getItemDetailsDao()
}

App.kt(更新)

package com.example.itemapp.data

import android.app.Application

    //  Creating a single instance of the DbRepository throughout the app. It is done in App class.
class App : Application() {

    companion object {
        lateinit var db: DbRepository
    }

    override fun onCreate() {
        super.onCreate()
        db = DbRepository.getInstance(applicationContext)
    }
}

    /*You can access the App class from any class of that module like this:
    App.db.itemDao().insertItems(data)
    Note: Remember to call these DB functions on a background thread.*/

AndroidManifest.xml(更新)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.itemapp">

    <application
        android:name=".App"   // Error.

        /* Class referenced in the manifest, com.example.itemapp.App, was not 
           found in the project or the libraries. Unresolved class 'App' */ 

        android:allowBackup="true"   
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name="com.example.itemapp.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

项目.kt

package com.example.itemapp.model

import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.android.parcel.Parcelize

@Parcelize
@Entity(tableName = "item_table")
data class Item(
    @PrimaryKey(autoGenerate = true)
    val id: Int,
    val firstName: String,
    val lastName: String,
    val item_value_a: String = "0"
    ): Parcelable

ItemOrderDetails.kt

package com.example.itemapp.model

import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.android.parcel.Parcelize

@Parcelize
@Entity(tableName = "item_order_details_table")
data class ItemOrderDetails(
    @PrimaryKey(autoGenerate = true)
    val id: Int,
    val item_group: String,
    val item_name: String,
    val item_value_b: String = "0",
    val item_base: String,
    val item_up: String
): Parcelable

表格的数据是...

Item.kt 数据

val item_data = listOf(
            Item("first_name_1", "last_name_1", "item_value_a_1"),
            Item("first_name_2", "last_name_2", "item_value_a_2"),
            Item("first_name_3", "last_name_3", "item_value_a_3")
)

ItemOrderDetails.kt 数据

val item_order_details_data = listOf(
            ItemOrderDetails("item_group_1", "item_name_1", "item-value_b_1", "item_base_1", "item_up_1"),
            ItemOrderDetails("item_group_2", "item_name_2", "item-value_b_2", "item_base_2", "item_up_2"),
            ItemOrderDetails("item_group_3", "item_name_3", "item-value_b_3", "item_base_3", "item_up_3")
)

【问题讨论】:

  • 您要ROOM操作吗?
  • 我只想有人给我我的 ItemDatabase.kt 文件的代码,即根据我的问题的代码。我读了很多关于这个的东西。我需要正确的代码来实现我的问题中描述的那些功能。
  • 为了预加载数据,ItemDatabase.kt 文件需要一些额外的代码。我有两张桌子。我不知道该怎么做。

标签: android kotlin android-room


【解决方案1】:

按照以下步骤操作:

  1. ItemOrderDetails 表创建另一个Dao,例如ItemDao

  2. Dao中添加以下方法:

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertItems(item: List<YourModelName>)
    
    @Query("SELECT * FROM YourModelName")
    suspend fun getAllItems(): List<YourModelName>
    

这些函数将帮助您从DB 获取项目并将项目插入其中。 OnConflictStrategy.REPLACE 将检查表中是否已经存在具有相同主键的项目。如果是,它将用新项目替换它。

  1. 将您的 ItemDatabase 类更改为:

    @Database(entities = [
        Item::class,
        ItemOrderDetails::class], version = 1)
    abstract class ItemDatabase: RoomDatabase() {
    
    abstract fun getItemDao(): ItemDao
    abstract fun getItemDetailsDao(): ItemOrderDetailsDao
    

    }

  2. 添加一个新类来访问DB

    class DbRepository (private val database: ItemDatabase) {
    
    companion object {
        private var instance: DbRepository? = null
    
        fun getInstance(context: Context): DbRepository {
            return instance ?: synchronized(this) {
                instance ?: DbRepository(initializeDb(context)).also { instance = it }
            }
        }
    
        private fun initializeDb(context: Context): ItemDatabase {
            return Room.databaseBuilder(
                context,
                ItemDatabase::class.java, "ItemDb"
            ).build()
        }
    }
    
    fun itemDao():ItemDao = database. getItemDao()
    
    fun itemDetailsDao():ItemOrderDetailsDao = database.getItemDetailsDao()
    

    }

  3. 在整个应用程序中创建 DbRepository 的单个实例,您可以在 App 类中执行此操作。

    class App: Application() {
    
    companion object {
        lateinit var db: DbRepository
    }
    
    override fun onCreate() {
        super.onCreate()
        db = DbRepository.getInstance(applicationContext)
    }
    

    }

  4. 您可以从该模块的任何类访问App 类,如下所示:

    App.db.itemDao().insertItems(data)

注意:记得在后台线程上调用这些DB 函数。


编辑 1.0

按照步骤在后台线程上调用DB 函数。

  1. 在您的 app's gradle file 中添加 implementation "androidx.fragment:fragment-ktx:1.2.5" 依赖项。

  2. 在您的DataFragment 中添加private val viewModel:ItemViewModel by viewModels()

  3. ItemRepository 类中添加一个新函数。


suspend fun addItems(items: List<Item>){
        itemDao.insertItems(item)
    }

  1. 在您的 ItemViewModel 类中添加一个新函数。

fun addItems(items: List<Item>){
        viewModelScope.launch {
            repository.addItems(items)
        }
    }

  1. 使用ItemViewModel 类中的函数从DataFragment 类调用DB 操作。

fun addItemsFromFragment(items: List<Item>){
        viewModel.addItems(items)
    }


编辑 1.1

在您的ItemDao 中添加此函数,并为ItemDetailsDao 执行相同操作。


@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertItems(item: List<Item>)


编辑 1.2

在您的ItemViewModel 中添加此功能。


fun addItems(items:List<Item>) {
   viewModelScope.launch {
       App.db.itemDao().insertItems(items)
   }
}

并从您的Fragment 调用此函数。


class DataFragment {

    companion object Data{
        var item_order : Int = 0
        var item_order_alert : Int = 0
        var selectedItems1 = arrayOf<Int>(0)

        var item_details_list = mutableListOf<ItemDetails>()
        
        val item_data = listOf(
            Item(0, "first_name_1", "last_name_1", "item_value_a_1"),
            Item(0, "first_name_2", "last_name_2", "item_value_a_2"),
            Item(0, "first_name_3", "last_name_3", "item_value_a_3")
        )

        val item_order_details_data = listOf(
            ItemOrderDetails(0, "item_group_1", "item_name_1", "item-value_b_1", "item_base_1", "item_up_1"),
            ItemOrderDetails(0, "item_group_2", "item_name_2", "item-value_b_2", "item_base_2", "item_up_2"),
            ItemOrderDetails(0, "item_group_3", "item_name_3", "item-value_b_3", "item_base_3", "item_up_3")
        )

        fun addItemsFromFragment(items: List<Item>){
            viewModel.addItems(items) // This will add your items. Remove lines which are causing error from your viewmodel.
        }

    }

}

【讨论】:

  • 我认为我在执行您的答案时犯了一个错误。我也有些疑惑。
  • 在应用您的答案后,我添加了 ItemRepository、ItemOrderDetailsDao 和 ItemDatabase。请尝试使用我使用过的相同变量,因为我是 Kotlin、Room 等的新手。我已经有一个工作项目,我正在尝试包含您的代码,以便我可以修改它。
  • 有一个 getDatabase() 函数,它在 ItemViewModel 和 ItemDatabase 中有用法。现在它显示错误。我想将您的代码包含在我的项目中。我可以理解你的代码,前提是它们在我的项目中使用了变量名。
  • 我将不得不查看您的代码以帮助您解决此问题。如果可能,请分享您遇到错误的代码。
  • 我项目中的主要文件有:ItemDatabase、ItemDao、ItemOrderDetailsDao、Item、ItemOrderDetails、ItemRepository和ItemViewModel。
猜你喜欢
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 2021-05-21
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多