HttpURLConnection → OkHttp + Kotlin
老写法(Java + HttpURLConnection)
java
new Thread(() -> {
HttpURLConnection connection = null;
try {
URL url = new URL("https://api.example.com/data");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
int code = connection.getResponseCode();
if (code == 200) {
InputStream is = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
final String result = sb.toString();
runOnUiThread(() -> updateUI(result));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) connection.disconnect();
}
}).start();
问题在哪里
手写 Socket 级别的连接管理、超时、流读取,代码量爆炸。线程切换全靠手动 new Thread + runOnUiThread。请求重试、缓存、HTTPS 证书校验全要自己实现,没有拦截器机制。
新写法(OkHttp + Coroutines)
添加依赖:
groovy
implementation "com.squareup.okhttp3:okhttp:4.12.0"
kotlin
private val client = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.build()
viewModelScope.launch(Dispatchers.IO) {
val request = Request.Builder()
.url("https://api.example.com/data")
.get()
.build()
try {
val response = client.newCall(request).execute()
if (response.isSuccessful) {
val result = response.body?.string() ?: ""
withContext(Dispatchers.Main) {
updateUI(result)
}
}
} catch (e: IOException) {
withContext(Dispatchers.Main) {
showError(e.message)
}
}
}
一句话注意
OkHttp 的 execute() 是同步方法,需要在后台线程调用。enqueue() 是异步回调,但用了协程就尽量用 execute() + 协程管理,避免回调嵌套。
response.body?.string() 只能调用一次,第二次返回空。如果需要反复读,先存到变量里。OkHttp 内部有自己的连接池和线程池,创建一次以单例使用即可,不要每次都 new。
Java Android 老项目迁移系列,持续更新中。