I am using SQLDelight with `generateAsync.set(*tru...
# squarelibraries
v
I am using SQLDelight with
generateAsync.set(*true*)
, now I found out that the suspend function created are not main safe As i am getting such ANR
Your app's code here results in the I/O call above. Code that triggers I/O operations should be moved out of the main thread.
Stack Trace in thread
Copy code
main (native):tid=1 systid=22205 
#00 pc 0x4f85c libc.so (syscall + 28) (BuildId: e78e5c1e0e8952bb7b108ea3094edf82)
#01 pc 0x232cec libart.so (art::ConditionVariable::WaitHoldingLocks + 140) (BuildId: 735f12f804f88d62a2cb437261076ff7)
#02 pc 0x4591d8 libart.so (artJniMethodEnd + 336) (BuildId: 735f12f804f88d62a2cb437261076ff7)
#03 pc 0x5bfd7c libart.so (art_jni_method_end + 12) (BuildId: 735f12f804f88d62a2cb437261076ff7)
       at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native method)
       at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:913)
       at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:756)
       at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:67)
       at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeUpdateDelete(FrameworkSQLiteStatement.java:38)
       at app.cash.sqldelight.driver.android.AndroidPreparedStatement.execute(AndroidSqliteDriver.kt:261)
       at app.cash.sqldelight.driver.android.AndroidSqliteDriver$execute$2.invoke(AndroidSqliteDriver.kt:184)
       at app.cash.sqldelight.driver.android.AndroidSqliteDriver$execute$2.invoke(AndroidSqliteDriver.kt:184)
       at app.cash.sqldelight.driver.android.AndroidSqliteDriver.execute-zeHU3Mk(AndroidSqliteDriver.kt:169)
       at app.cash.sqldelight.driver.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:184)
       at database.FeedItemEntityQueries.insert(FeedItemEntityQueries.kt:315)
       at com.medial.app.data.local.datasource.FeedItemDataSource.insert(FeedItemDataSource.kt:53)
       at com.medial.app.data.repo.ugc.FeedItemRepository$getReplyFeedItemsPaged$2.invokeSuspend(FeedItemRepository.java:55)
       at com.medial.app.data.repo.ugc.FeedItemRepository$getReplyFeedItemsPaged$2.invoke(FeedItemRepository.java:20)
       at com.medial.app.data.repo.ugc.FeedItemRepository$getReplyFeedItemsPaged$2.invoke(FeedItemRepository.java:12)
       at com.medial.app.data.repo.paging.MediatorRepo.load(MediatorCall.kt:82)
       at com.medial.app.data.repo.paging.MediatorRepo$load$1.invokeSuspend(MediatorCall.kt:1)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
       at android.os.Handler.handleCallback(Handler.java:984)
       at android.os.Handler.dispatchMessage(Handler.java:104)
       at android.os.Looper.loopOnce(Looper.java:238)
       at android.os.Looper.loop(Looper.java:357)
       at android.app.ActivityThread.main(ActivityThread.java:8109)
       at java.lang.reflect.Method.invoke(Native method)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:957)
d
That's correct. You're still responsible for dispatching the call to an appropriate thread
v
But shouldn't libraries providing suspend function make it main safe out of the box?
d
Not necessarily. For some environments (web and R2DBC) the database calls are inherently asynchronous, and the suspending codegen exists to support those use cases. For all of the other environments, the regular codegen is fine. The reason it will still generate a suspending function even though the underlying call is blocking is to support multiplatform use cases where you could have a web and Android target sharing their database code (for example). If you're not targeting an environment that needs an asynchronous driver, there's no benefit to doing so.