异步获取Android Kotlin中的URL

所以我试图编写一个非常简单的Android应用程序,当按钮被按下时从URL获取响应。 kotlin Android扩展已经被广告作为Java中必要的样板的替代品,所以我试了我的手。 这是我到目前为止所尝试的:

package com.example.susemihl.myapplication import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.widget.TextView import kotlinx.android.synthetic.main.activity_main.* import kotlinx.coroutines.experimental.CommonPool import kotlinx.coroutines.experimental.async import kotlinx.coroutines.experimental.runBlocking import java.net.URL suspend fun fetch_url(url: String): String { return URL(url).readText() } fun fetch_async(url: String, view: TextView) = runBlocking { val result = async(CommonPool) { fetch_url(url) } view.setText(result.await()) } class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mainTextView.setText("Hello there.") mainButton.setOnClickListener { mainButton.setText("Check again.") fetch_async("https://random-app.appspot.com/", mainTextView) } } } 

这个间歇性的工作,但现在完全破碎。 没有响应按钮点击。 打印调试显示线程得到执行,但似乎挂在readText()调用。 我在这里做错了什么蠢事?

我想你正在寻找这样的事情

 async { val result = URL("url").readText() uiThread { mainTextView.setText(result) } } 

除非我错了,否则你的代码看起来就像在UI线程上阻塞,而不是等待响应第一次返回

我知道你的情况,这是因为你正在使用runBlocking ,尽管await不会阻塞线程,但它会暂停协程,并且由于当前协程没有完成, runBlocking线程将被阻塞等待它。

所以只需使用runBlocking launc(UI)而不是runBlocking来解决这个问题:

 package com.example.susemihl.myapplication import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.widget.TextView import kotlinx.android.synthetic.main.activity_main.* import kotlinx.coroutines.experimental.CommonPool import kotlinx.coroutines.experimental.android.UI import kotlinx.coroutines.experimental.async import kotlinx.coroutines.experimental.launch import java.net.URL fun fetch_url(url: String): String { return URL(url).readText() } fun fetch_async(url: String, view: TextView) = launch(UI) { val result = async(CommonPool) { fetch_url(url) } view.text = result.await() } class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mainTextView.text = "Hello there." mainButton.setOnClickListener { mainButton.text = "Check again." fetch_async("https://jacksgong.com", mainTextView) } } } 

这是一个异步样本,可以与kotlin一起使用,这对我来说是完美的

 val result = URL("").readText() 

 try { URL url = new URL(""); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestMethod("GET"); urlConnection.connect(); InputStream inputStream = urlConnection.getInputStream(); StringBuffer buffer = new StringBuffer(); if (inputStream == null) { // Nothing to do. return null; } reader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = reader.readLine()) != null) { buffer.append(line + "\n"); } if (buffer.length() == 0) { return null; } result = buffer.toString(); } catch (IOException e) { Log.e("Request", "Error ", e); return null; } finally{ if (urlConnection != null) { urlConnection.disconnect(); } if (reader != null) { try { reader.close(); } catch (final IOException e) { Log.e("Request", "Error closing stream", e); } } } 

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); task = new AsyncTask() { @Override protected String doInBackground(Void... params) { return requestFromServer(""); } @Override protected void onPostExecute(String s) { if (!isFinishing() && !isCancelled()) { Log.d("Request", s); Toast.makeText(ExampleActivity.this, "Request performed", Toast.LENGTH_LONG).show(); } } }; } @Override protected void onDestroy() { super.onDestroy(); if (task != null) { task.cancel(true); task = null; } } 

参考 – antonioleiva