NetworkOnMainThreadException与Kotlin协程中的URL()。readText()

时间:2019-04-01 13:10:26

标签: android url kotlin

我正在android studio中工作,并且正在使用kotlin协程从API检索结果。

我需要等到协程完成后,才能从中分配一个全局变量。

我已经测试了URL,没关系。 我尝试了正常的线程,该线程可以工作,但是无法让主线程等待其完成。

我尝试使用Fuel.get(),但工作正常,但想使用URL()。

var response = "";
val req = "url.com"
runBlocking { launch {
            response = URL(req).readText()
} }

谁能告诉我为什么此代码不起作用?它引发了NetworkOnMainThreadException,但被包装在协程中。

4 个答案:

答案 0 :(得分:0)

尝试这种方式

var response = "";
val req = "url.com"
runBlocking<Unit> { 
GlobalScope.launch {
    response = URL(req).readText()
}
    //Work with the response here
}

您可以预览所有协程文档here

答案 1 :(得分:0)

如果只想在另一个线程中处理URL(req).readText()的结果,请执行以下代码。

var response = "";
val req = "url.com"
runBlocking<Unit> { 
GlobalScope.launch {
    response = URL(req).readText()
    //here is another thread,handle response here
}
 //here is main thread, you can't get the result of URL(req).readText() because io operation need a long time .

}

如果在主线程中处理结果,请使用Hanlder类

答案 2 :(得分:0)

我修复了它。最终使用AsyncTask读取URL,并使用Handler安排处理结果。

var response = ""

@SuppressLint("StaticFieldLeak")
inner class Retriever : AsyncTask<String, String, String>() {
      override fun doInBackground(vararg args : String?): String {
            val urlRequest = args[0].toString()
            var urlResponse = "";

            //Try to extract url
            try {
                urlResponse = URL(urlRequest).readText()
                println("SUCCESS in Retrieve.")
            } catch (e : Exception) {
                println("EXCEPTION in Retrieve.")
                e.printStackTrace()
            }
            return urlResponse;
        }

        //Assigns value to response
        override fun onPostExecute(result: String?) {
            response = result.toString() //Result possibly void type
    }
}

override fun onCreate() {
    Retriever().execute("url.com")
    Handler().{/*Handle response here*/, 10000)
}

答案 3 :(得分:0)

对我来说,以下代码可以正常运行。

var response = "";
val req = "yoururl.com"
runBlocking {    
 try {
  withTimeout(5000) {  // 5 seconds for timeout
    launch(Dispatchers.IO) {    // using IO Dispatcher and not the default
     response = URL(req).readText()
    } // launch
  } // timeout
 } catch (e:Exception) {  // Timeout, permission, URL or network error
   response="Error"   // Here one uses a not valid message
 }
 // Here one manages 'response' variable for error handling or valid output.

AndroidManifest.xmlmanifest标签内添加权限也很重要:

<uses-permission android:name="android.permission.INTERNET"/>

(对于时间不太长的任务)这种方法的优点是简单,因为它是顺序代码,因此不需要使用callback例程。