这是我的程序,用于显示我在Android设备上制作的Web应用(数据产品)的结果。
package studio.nyaa.crimeprediction
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import java.net.URL
import android.util.Log
import android.widget.TextView
import com.beust.klaxon.JsonObject
import com.beust.klaxon.Parser
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.async
suspend fun obtainJson():JsonObject {
val sourceURL = "http://yingzhou474.pythonanywhere.com/api"
val jsonRes: String = URL(sourceURL).readText()
val parser: Parser = Parser.default()
val json = parser.parse(jsonRes) as JsonObject
Log.d("oj", "oj finished")
return json
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runBlocking {
val json = async{obtainJson()}.await()
Log.d("postcoroutine", json.toString())
val crime1: Double? = json.obj("data")?.double("AGGRAVATED ASSAULT")
val crime2: Double? = json.obj("data")?.double("AUTO THEFT")
val crime3: Double? = json.obj("data")?.double("COMMERCIAL BURGLARY")
val crime4: Double? = json.obj("data")?.double("HOMICIDE")
val crime5: Double? = json.obj("data")?.double("LARCENY")
val crime6: Double? = json.obj("data")?.double("OTHER BURGLARY")
val crime7: Double? = json.obj("data")?.double("RESIDENTIAL BURGLARY")
val crime8: Double? = json.obj("data")?.double("ROBBERY")
val year: Int? = json.int("year")
val month: Int? = json.int("month")
val day: Int? = json.int("day")
val textView1: TextView = findViewById(R.id.editText1B)
textView1.text = crime1?.toString() ?: "N/A"
val textView2: TextView = findViewById(R.id.editText2B)
textView2.text = crime2?.toString() ?: "N/A"
val textView3: TextView = findViewById(R.id.editText3B)
textView3.text = crime3?.toString() ?: "N/A"
val textView4: TextView = findViewById(R.id.editText4B)
textView4.text = crime4?.toString() ?: "N/A"
val textView5: TextView = findViewById(R.id.editText5B)
textView5.text = crime5?.toString() ?: "N/A"
val textView6: TextView = findViewById(R.id.editText6B)
textView6.text = crime6?.toString() ?: "N/A"
val textView7: TextView = findViewById(R.id.editText7B)
textView7.text = crime7?.toString() ?: "N/A"
val textView8: TextView = findViewById(R.id.editText8B)
textView8.text = crime8?.toString() ?: "N/A"
val textViewDate: TextView = findViewById(R.id.editTextDate)
textViewDate.text = "Date: $month/$day/$year"
}
}
}
这里的数据源是this site,它返回这种JsonObject:
{"data": {"AGGRAVATED ASSAULT": 6.87, "AUTO THEFT": 4.4, "COMMERCIAL BURGLARY": 1.3, "HOMICIDE": 0.62, "LARCENY": 30.72, "OTHER BURGLARY": 0.59, "RESIDENTIAL BURGLARY": 4.21, "ROBBERY": 3.16}, "year": 2019, "month": 8, "day": 20}
Edited2:我自己修复了Klaxon错误。
编辑:现在解决了这个问题后,我得到了其他东西:
08-19 23:13:32.385 2175-2175/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: studio.nyaa.crimeprediction, PID: 2175
java.lang.RuntimeException: Unable to start activity ComponentInfo{studio.nyaa.crimeprediction/studio.nyaa.crimeprediction.MainActivity}: java.io.FileNotFoundException: {"data": {"AGGRAVATED ASSAULT": 6.87, "AUTO THEFT": 4.4, "COMMERCIAL BURGLARY": 1.3, "HOMICIDE": 0.62, "LARCENY": 30.72, "OTHER BURGLARY": 0.59, "RESIDENTIAL BURGLARY": 4.21, "ROBBERY": 3.16}, "year": 2019, "month": 8, "day": 20}: open failed: ENOENT (No such file or directory)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2404)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2466)
at android.app.ActivityThread.access$900(ActivityThread.java:175)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1369)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5418)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1037)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
Caused by: java.io.FileNotFoundException: {"data": {"AGGRAVATED ASSAULT": 6.87, "AUTO THEFT": 4.4, "COMMERCIAL BURGLARY": 1.3, "HOMICIDE": 0.62, "LARCENY": 30.72, "OTHER BURGLARY": 0.59, "RESIDENTIAL BURGLARY": 4.21, "ROBBERY": 3.16}, "year": 2019, "month": 8, "day": 20}: open failed: ENOENT (No such file or directory)
at libcore.io.IoBridge.open(IoBridge.java:456)
at java.io.FileInputStream.<init>(FileInputStream.java:76)
at com.beust.klaxon.Parser$DefaultImpls.parse(Parser.kt:21)
at com.beust.klaxon.KlaxonParser.parse(KlaxonParser.kt:9)
at studio.nyaa.crimeprediction.MainActivityKt.obtainJson(MainActivity.kt:16)
at studio.nyaa.crimeprediction.MainActivity$onCreate$1$json$1.invokeSuspend(MainActivity.kt:25)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:442)
at java.io.FileInputStream.<init>(FileInputStream.java:76)
at com.beust.klaxon.Parser$DefaultImpls.parse(Parser.kt:21)
at com.beust.klaxon.KlaxonParser.parse(KlaxonParser.kt:9)
at studio.nyaa.crimeprediction.MainActivityKt.obtainJson(MainActivity.kt:16)
at studio.nyaa.crimeprediction.MainActivity$onCreate$1$json$1.invokeSuspend(MainActivity.kt:25)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
08-19 23:13:32.555 2175-2175/? I/Process: Sending signal. PID: 2175 SIG: 9
旧内容:
尽管使用async
和await
,我仍然得到了android.os.NetworkOnMainThreadException
。这是我的堆栈跟踪:
08-19 22:28:06.675 28015-28015/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: studio.nyaa.crimeprediction, PID: 28015
java.lang.RuntimeException: Unable to start activity ComponentInfo{studio.nyaa.crimeprediction/studio.nyaa.crimeprediction.MainActivity}: android.os.NetworkOnMainThreadException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2404)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2466)
at android.app.ActivityThread.access$900(ActivityThread.java:175)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1369)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5418)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1037)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147)
at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at com.android.okhttp.HostResolver$1.getAllByName(HostResolver.java:29)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:232)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:124)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:272)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:382)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:332)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:199)
at java.net.URL.openStream(URL.java:470)
at kotlin.io.TextStreamsKt.readBytes(ReadWrite.kt:150)
at studio.nyaa.crimeprediction.MainActivityKt.obtainJson(MainActivity.kt:17)
at studio.nyaa.crimeprediction.MainActivity$onCreate$1$json$1.invokeSuspend(MainActivity.kt:28)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:270)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:79)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at studio.nyaa.crimeprediction.MainActivity.onCreate(MainActivity.kt:27)
at android.app.Activity.performCreate(Activity.java:6083)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1115)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2357)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2466)
at android.app.ActivityThread.access$900(ActivityThread.java:175)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1369)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5418)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1037)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
这个问题是my earlier question的变体。
答案 0 :(得分:8)
这是因为异步块正在与 Dispatchers.Main 一起运行,并尝试与 Dispatchers.IO
一起使用val json = async(Dispatchers.IO){obtainJson()}.await()
另外一种更好的语法是使用withContext
val json = withContext(Dispatchers.IO){obtainJson()}
答案 1 :(得分:1)
您不应在主线程中调用网络。您可以使用IO
调度程序来修复它:
async(Dispatchers.IO){ obtainJson() }.await()
答案 2 :(得分:0)
您不应在生产代码中使用runBlocking {}
!它将阻塞您的主线程。
由于您是在主线程中调用此函数,因此随后每次对async
或launch
的调用都将在相同的作用域内运行,并因此在主线程上运行。
相反,您应该使用viewModelScope
启动一个协程(也可以使用GlobalScope
)并在主线程上运行视图更新:
GlobalScope.launch(IO) {
val json = obtainJson()
Log.d("postcoroutine", json.toString())
val crime1: Double? = json.obj("data")?.double("AGGRAVATED ASSAULT")
...
val year: Int? = json.int("year")
val month: Int? = json.int("month")
val day: Int? = json.int("day")
launch(Main) {
val textView1: TextView = findViewById(R.id.editText1B)
textView1.text = crime1?.toString() ?: "N/A"
...
val textViewDate: TextView = findViewById(R.id.editTextDate)
textViewDate.text = "Date: $month/$day/$year"
}
}
此处无需使用async
。可以使用launch(Main)
代替withContext(Main)
。