0

Everything works (Insert, Update, Delete with AsyncTask) fine, but getting a single row by id not...

The main problem is that there are two Activities.

  1. A RecyclerView
  2. Details page

I would like to get one item by id from the Database after clicked on a RecyclerView list item. If I get it with LiveData I can not synchronize it with a variable in the UI thread.

How can you get a single row from Database?

in the DAO I have:

@Query("SELECT * FROM codes WHERE id = :id")
Code getCodeById(int id);

in the Repository:

public Code retrieveCode(int id){
    return myDatabase.getCodeDao().getCodeById(id);
}

If I write it in the main thread

selectedCode = mCodeRepository.retrieveCode(codeId);

it gives an error:

 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.

Should I use AsyncTask, but how?

froniq
  • 105
  • 1
  • 8
  • "Should I use AsyncTask" -- no. "How can you get a single row from Database?" -- you already have the code for that. All database operations need to be performed on a background thread. For queries in Java, the typical approaches are to have the DAO return `LiveData` or an RxJava type (e.g., `Single`, `Observable`). "If I get it with LiveData I can not synchronize it with a variable in the UI thread" -- you might want to ask a separate question, where you can provide a [mcve] showing what you tried for this. – CommonsWare Oct 16 '20 at 19:11
  • I have a little example here: https://stackoverflow.com/questions/64396258/if-i-get-a-row-from-database-with-room-and-livedata-how-can-i-synchronize-it – froniq Oct 16 '20 at 20:54

1 Answers1

0

There are few things you can do to resolve this issue. You are using java in this case. So,first of all why android asking you to not call on UI thread? In android whenever you launch an app it will get associated with one process and it will run on main thread which is UI thread. All the operations by default run on ui thread. And mainly all operation which involves instance of UI should run on UI Thread. Now whenever you call an API or call database to retrieve data, it might take some time. So, if you run this operation on UI thread then what could happen is It will block all the operation as one heavy loading task is in process and thats why it could crash or can give you error that you cant run it on main thread.

to resolve this you can use

App.db = Room.databaseBuilder(this, AppDb::class.java,"Your DB Name")
                     .allowMainThreadQueries()
                     .build()

and it will allow you to call on mainthread. This is the simplest and straight forward.

Or You can go with asyncTask approach.

Karsh Soni
  • 170
  • 1
  • 12
  • "This is the simplest and straight forward" -- it is also completely awful. Do not do disk I/O on the main application thread, please. "You can go with asyncTask approach" -- `AsyncTask` is deprecated. – CommonsWare Oct 16 '20 at 21:37
  • Yes AsyncTask is deprecated but i think for a beginner it would be good if they first learn and use asynctask and then move forward to other approaches.@CommonsWare – Karsh Soni Oct 17 '20 at 04:25