0

I am trying to get the user ID from the newest user. How can I make the insert method spit the ID when the ID is autogenerated?

in Model

@PrimaryKey(autoGenerate = true)
    val userId: Int

in Dao

@Insert(onConflict = OnConflictStrategy.REPLACE)
   fun addUserWithLong(user: User): LiveData<Long>

in Repository

fun addUserWitLong(user: User): LiveData<Long> {
        return userDao.addUserWithLong(user)
    }

in ViewModel

fun addUserWithLong(user: User): LiveData<Long> {
        return repository.addUserWitLong(user)
    }

in Fragment

val id: Long? = userViewModel.addUserWithLong(user).value

I have read in the docs that @Insert returns Long as the row ID but I do not know how to program it. Now the error is "Not sure how handle insert method return type." Is there some way to make with LiveData and not with Rxjava. That is without the need to download more dependecies.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Tbijo54
  • 65
  • 6

1 Answers1

2

As per the documentation here

If the @Insert method receives a single parameter, it can return a long value, which is the new rowId for the inserted item. If the parameter is an array or a collection, then the method should return an array or a collection of long values instead, with each value as the rowId for one of the inserted items. To learn more about returning rowId values, see the reference documentation for the @Insert annotation, as well as the SQLite documentation for rowid tables

So you can use it like

   @Insert(onConflict = OnConflictStrategy.REPLACE)
   long addUserWithLong(user: User)

or if you are inserting a list

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    long[] addUserWithLong(user: List<User>)

Edit-1

After checking answers from this post.

No, you can't. I wrote an answer to the issue. The reason is, that LiveData is used to notify for changes. Insert, Update, Delete won't trigger a change.

I just created a test project and successfully received Id of last inserted item in activity. Here is my implementation.

Dao

@Insert
suspend fun addUser(user: Users): Long

Repo

suspend fun insertUser(context: Context, users: Users): Long {
        val db = AppDatabase.getInstance(context)
        val dao = db.userDao()
        return dao.addUser(users)
    }

ViewModel

 fun addUser(context: Context, users: Users) = liveData {
//you can also emit your customized object here. 
        emit("Inserting...")
        try {
            val userRepo = UsersRepo()
            val response = userRepo.insertUser(context, users)
            emit(response)
        } catch (e: Exception) {
            e.printStackTrace()
            emit(e.message)
        }
    }

Activity

viewModel.addUser(applicationContext, user).observe(this, Observer { userId ->
            Log.d("MainActivity", "Inserted User Id is $userId")
        })

Check test application here.

Imran Ali
  • 321
  • 2
  • 13
  • I understand that but I am supposed to call the function from not the main thread. And do not know how to achieve that with out LiveData. – Tbijo54 Aug 29 '21 at 15:48
  • If you want it with livedata than in fragment/activity you should do this. Rest of your code if fine. viewModel.addUserWitLong(user).observe(viewLifecycleOwner,{id-> Tiimber.d( "Inserted ID is $id") }) – Imran Ali Aug 29 '21 at 16:04
  • I keep getting this error in Dao. error: Not sure how to handle insert method's return type. – Tbijo54 Aug 29 '21 at 16:20
  • And I do not want it specifically with LiveData I just need to get it not from main thread. I thought using LiveData or make the function suspend. But I do not know how to make it work either way. – Tbijo54 Aug 29 '21 at 16:28
  • It works well enough. But it takes a little while to get the ID. And since I am using fragment in observe I replaced this with viewLifeCycleOwner. It worked with requireActivity as well. The ID should not be used inside the Observer{} because it takes a while to aquire it. – Tbijo54 Aug 30 '21 at 15:33