我正在尝试将列表中的数据写入特定的 Google 表格。我已经设置了配置,但遇到了一个似乎与不使用协程相关的错误。
我的做法正确吗?有没有办法在没有协程的情况下实现这一点,因为我不确定如何实现它们?如果需要协程,如何正确集成它们?
触发设备上的按钮时发生错误,导致应用程序关闭:
FATAL EXCEPTION: main
Process: com.nase.naseapp, PID: 26027
android.os.NetworkOnMainThreadException
...
...
...
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@13df640, androidx.compose.runtime.BroadcastFrameClock@de98979, StandaloneCoroutine{Cancelling}@e896be, AndroidUiDispatcher@5ea431f]
有问题的类包含按钮的
onClick
函数调用的方法:
class SheetsAPI(private val application: Application, credential: GoogleCredential) {
private val jsonFactory = JacksonFactory.getDefaultInstance()
private val httpTransport = NetHttpTransport()
private val service: Sheets = Sheets.Builder(httpTransport, jsonFactory, credential)
.setApplicationName(application.getString(R.string.app_name))
.build()
fun submitExpensesToGoogleSheet(expenses: List<ExpenseData>){
val spreadsheetId = "_____spreadsheetid____"
val range = "Sheet1!A1:B2"
val valueRange = ValueRange().setValues(
listOf(
listOf("Expense", "Amount"),
*expenses.map { listOf(it.title, it.amount) }.toTypedArray()
)
)
service.spreadsheets().values().update(spreadsheetId, range, valueRange)
.setValueInputOption("RAW")
.execute()
println("Sending data to Sheet")
}
}
任何关于为什么会发生
NetworkOnMainThreadException
的见解以及关于实现协程或替代方案的指导将受到高度赞赏。谢谢!
正如您所说并分享的那样,您收到了 NetworkOnMainThreadException。在以下情况下抛出此异常:
“...应用程序尝试在其上执行网络操作 主线程。” 参考
您之所以会遇到此异常,是因为您在以下几行中的逻辑:
service.spreadsheets().values().update(spreadsheetId, range, valueRange)
.setValueInputOption("RAW")
.execute()
上面的调用是执行网络请求的调用,您不能在主线程上执行这些请求,因为它们:
为了克服这个问题,可以使用协程来处理网络请求结果的调用和获取。您还可以使用其他组件。
如何将逻辑包装在协程中的示例如下:
suspend fun submitExpensesToGoogleSheet(expenses: List<ExpenseData>) {
val spreadsheetId = "_____spreadsheetid____"
val range = "Sheet1!A1:B2"
val valueRange = ValueRange().setValues(
listOf(
listOf("Expense", "Amount"),
*expenses.map { listOf(it.title, it.amount) }.toTypedArray()
)
)
withContext(Dispatchers.IO) {
service.spreadsheets().values().update(spreadsheetId, range, valueRange)
.setValueInputOption("RAW")
.execute()
println("Sending data to Sheet")
}
}
}
请注意,您需要将您的方法设为挂起方法,并从另一个挂起方法或协程内部调用该方法。 您可以在此处阅读有关协程的更多信息。