6

I'm trying to figure out the best way to fetch a single row via Room by ID. I have copied code from a guide on how to fetch all my rows in an entity (Workout plus all the joined entities) and that works great for populating a recyclerview.

But when I need to drill down to just one, currently, my guess code in the repository is

@WorkerThread
suspend fun getWorkoutById(id: Long): LiveData<WorkoutTree> {
    return workoutDao.getWorkoutById(id)
}

and in the DAO

@Transaction
@Query("SELECT * FROM WORKOUTS WHERE id=:id")
fun getWorkoutById(id: Long): LiveData<WorkoutTree>

Naturally I call repository.getWorkoutById(myId) from my ViewModel so I can populate the data and reference it from my Activity/Fragment.

But I'm trying to figure out whether I'm on the right track and the best way to be fetching this. It's a DB local to the phone, so shouldn't be issues of needing live updates, honestly.

Would it be better to just serialize the object tapped in the Recyclerview listing all rows and pass that into my activity and not bother to fetch by ID?

Pretty much every example I find online about Room and Android development gives examples for fetching all rows and use LiveData and the repository has a public property that is LiveData> populated by an initial DAO fetch of all rows from the entity.

I'm having difficulty translating this example mentally into one where I'd just fetch one row.

I don't really have any functioning code to share since I can't really figure out how to architect this in Kotlin and Room and such. I've never written an Android app before and come from a functional programming background via Python, JS, Scala and so am struggling with how Kotlin guides and Android guides recommend you do this with all the additional classes and interfaces used to decouple everything for a phone app.

user1713450
  • 1,307
  • 7
  • 18
  • `@Query("SELECT * FROM WORKOUTS WHERE id=:id LIMIT 1")` ? – Taseer May 01 '19 at 06:05
  • Id is unique. I'm more asking about the connection between dao and repo and Viewmodel, how to transfer the result. – user1713450 May 01 '19 at 13:24
  • Should I return livedata? Single? Maybe? Should my repo get by id return an object, or void and have a mutable that belongs to the repo class that updates when you get by id? That is my question: architectural – user1713450 May 01 '19 at 13:27
  • @user1713450 Have you find the right way to do it? Could you give us an answer please. – Francky380 May 19 '20 at 15:31

2 Answers2

3

You should never, as good practice, load all the data when you need just part of it. Whether this is a desktop or a mobile application you should always load just what you need. That said you are on the right track. Since you are only loading a single row the @Transaction annotation is not needed. Other than that if id is declared with annotation of @PrimaryKey(autoGenerate = true) than the getWorkoutById should work just fine.

If you are looking for a good tutorial about Room you can do this short free tutorial Android Architecture Components. Jump straight to lesson 8 as it is not relying on the previous lessons.

If on the other hand you just want an example, have a look at this app from the tutorial. To be more specific look at the DAO object here. You'll see that is exactly what you did except it is written in Java.

Itamar Kerbel
  • 2,508
  • 1
  • 22
  • 29
  • The example shows: @Query("SELECT * FROM task WHERE id = :id") TaskEntry loadTaskById(int id); which does not return a single LiveData record. So it seems like the answer is not to use live data for single records, is that right? – lcj May 30 '21 at 12:29
  • why do you say it will not return a single row? If the Id is unique it should return just one row... – Itamar Kerbel May 31 '21 at 05:25
  • A single LiveData record. It returns a single object, which is fine. I think there original question is around the best way to return a single record. I have had challenges with LiveData in this regard. I love it for lists but not really for single records, particularly if I am doing a series of operations. I’m pleased the example shows a pojo returned for the single record query. – lcj May 31 '21 at 11:28
0

in case anyone still in search limit offset works fine on room + additional where condition

@Query("SELECT * FROM ziyaret WHERE uniq= :mUniq LIMIT :limit OFFSET :offset")
    fun getFirstColumn(mUniq: Long, limit: Int, offset: Int): List<Ziyaret>



var first = ziyaretDao.getFirstColumn(myUni, 1, 0) as ArrayList<Ziyaret>

(..,1,0) it will return first row from table, u may set the range thx to

Samir
  • 6,405
  • 5
  • 39
  • 42