Phalaen
Phalaen

Reputation: 61

Obtaining an array from room Database - Android, Kotlin

I'm new with Room Database and I would like to extract from one database an array of int. I think that the problem is in the code of the fragment, when I would like to use the function "stationlist" to obtain an array of the codes of stations present in database. The output "StationList" seems to be Unit instead of Array: does anyone know the solution? Thank you

This is my entity and data class:

    @Parcelize
@Entity(tableName = "user_table")
data class User(
    @PrimaryKey(autoGenerate = true)
    val id: Int,
    val Name: String,
    val StationCode: Int
): Parcelable

This is my Dao:

@Dao
interface UserDao {

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun addUser(user: User)

    @Query("SELECT intArrayOf(StationCode) FROM user_table")
    suspend fun stationlist() : Array
}

This is my database:

@Database(entities = [User::class], version = 1, exportSchema = false)
abstract class UserDatabase : RoomDatabase() {

    abstract fun userDao(): UserDao

    companion object {
        @Volatile
        private var INSTANCE: UserDatabase? = null

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

}

This is my Repository:

class UserRepository(private val userDao: UserDao) {

    val readAllData: LiveData<List<User>> = userDao.readAllData()

    suspend fun addUser(user: User){
        userDao.addUser(user)
    }

    suspend fun stationlist(){
        userDao.stationlist()
    }

 }

and this is my Viewmodel:

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

    val readAllData: LiveData<List<User>>
    private val repository: UserRepository

    init {
        val userDao = UserDatabase.getDatabase(
            application
        ).userDao()
        repository = UserRepository(userDao)
        readAllData = repository.readAllData
    }

       fun addUser(user: User){
        viewModelScope.launch(Dispatchers.IO) {
            repository.addUser(user)
        }
    }

 fun stationlist(){
        viewModelScope.launch(Dispatchers.IO) {
            repository.stationlist()
        }
    }

}

At last this is a part of the fragment:

class AddFragment : Fragment(), OnMapReadyCallback {

    private lateinit var mUserViewModel: UserViewModel
override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
  // here is all the part regarding displaying the layout and collecting data

mUserViewModel = ViewModelProvider(this).get(UserViewModel::class.java)

        view.add_btn.setOnClickListener {
            insertDataToDatabase()
        }
        return view
    }

private fun insertDataToDatabase() {
if(inputCheck(name, stationcode)){
                val user = User(
                0,
                name,
                stationcode)
            mUserViewModel.addUser(user)

// Here is the problem:
 
val StationList= mUserViewModel.stationlist()


   }

Upvotes: 0

Views: 756

Answers (1)

Rolud
Rolud

Reputation: 154

The problem is the dao method. Change it with this:

@Query("SELECT StationCode FROM user_table")
suspend fun stationlist() : Array<Int>

EDIT

There are some other problems with coroutines. In fragment you call this:

val StationList= mUserViewModel.stationlist()

But this method does not return immediately.

fun stationlist(){
    viewModelScope.launch(Dispatchers.IO) {
        repository.stationlist()
    }
}

You should implement a live data array, which is updated when async db query returns. In this way:

val stationList: MutableLiveData<Array<Int>>() = MutableLiveData()
fun stationlist(){
    viewModelScope.launch(Dispatchers.IO) {
        stationList.value = repository.stationlist()
    }
}

And in fragment you have to observe the list:

mUserViewModel.stationList.observe(viewLifecycleOwner) { array ->
    // do stuff
}

You also have to change repository stationlist() return type:

suspend fun stationlist(): Array<Int> {
    return userDao.stationlist()
}

These are useful links to understand coroutines, room and livedata:

Upvotes: 2

Related Questions