Android原生如何运行多个URL连接?含双连接代码示例
嘿,我来帮你搞定Android原生环境下多网络连接的实现问题!看你现在用的是AsyncTask,先给你提个醒:AsyncTask在API 30之后已经被标记为废弃了,不过我会先基于你现有的代码逻辑调整,同时也会给你推荐更现代的替代方案,方便你后续选择。
方案一:基于现有AsyncTask的改造
你当前的代码是用单个AsyncTask处理一个请求,要同时跑两个网络连接,有两种常见思路:
1. 启动两个独立的AsyncTask实例
把AsyncTask改成通用模板,通过构造函数传入目标URL和对应的UI控件,这样就能复用同一个类处理不同请求,并行执行两个任务:
public class MyPublicClass extends AppCompatActivity { private TextView mytxtview1; private TextView mytxtview2; private ProgressDialog progress; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mytxtview1 = findViewById(R.id.txt_view_1); mytxtview2 = findViewById(R.id.txt_view_2); progress = new ProgressDialog(this); progress.setMessage("加载中..."); progress.show(); // 启动第一个网络请求 new NetworkTask("url1", mytxtview1).execute(); // 启动第二个网络请求 new NetworkTask("url2", mytxtview2).execute(); } // 通用网络请求AsyncTask子类 private class NetworkTask extends AsyncTask<String, Void, String> { private String targetUrl; private TextView targetTextView; public NetworkTask(String url, TextView textView) { this.targetUrl = url; this.targetTextView = textView; } @Override protected String doInBackground(String... params) { StringBuilder output = new StringBuilder(); try { URL url = new URL(targetUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = reader.readLine()) != null) { output.append(line); } reader.close(); connection.disconnect(); } catch (Exception e) { e.printStackTrace(); return "请求失败:" + e.getMessage(); } return output.toString(); } @Override protected void onPostExecute(String result) { super.onPostExecute(result); // onPostExecute本身就在主线程,无需额外调用runOnUiThread targetTextView.setText(result); // 检查两个请求是否都完成,完成后关闭进度条 if (!TextUtils.isEmpty(mytxtview1.getText()) && !TextUtils.isEmpty(mytxtview2.getText())) { if (progress.isShowing()) progress.dismiss(); } } } }
2. 在单个AsyncTask里串行处理两个请求
如果需要两个请求按顺序执行(比如第一个请求完成后再执行第二个),可以把网络请求逻辑抽取成独立方法,在doInBackground里依次调用:
private class SerialNetworkTask extends AsyncTask<Void, Void, String[]> { @Override protected String[] doInBackground(Void... voids) { String[] results = new String[2]; // 串行执行两个请求 results[0] = fetchData("url1"); results[1] = fetchData("url2"); return results; } @Override protected void onPostExecute(String[] results) { super.onPostExecute(results); mytxtview1.setText(results[0]); mytxtview2.setText(results[1]); if (progress.isShowing()) progress.dismiss(); } // 通用网络请求方法 private String fetchData(String urlStr) { StringBuilder output = new StringBuilder(); try { URL url = new URL(urlStr); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = reader.readLine()) != null) { output.append(line); } reader.close(); connection.disconnect(); } catch (Exception e) { e.printStackTrace(); return "请求失败:" + e.getMessage(); } return output.toString(); } }
启动这个任务只需要一行代码:new SerialNetworkTask().execute();
方案二:更现代的替代方案(推荐)
由于AsyncTask已被废弃,Android官方推荐使用Coroutines(协程)或OkHttp来处理网络请求,代码更简洁,也能避免AsyncTask的潜在问题(比如内存泄漏、配置变更异常)。
用Coroutines实现并行请求
先在项目的build.gradle中添加协程依赖:
dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3" }
然后用Kotlin协程实现并行请求(如果是Java项目,也可以使用协程的Java API,不过Kotlin写法更简洁):
class MyPublicClass : AppCompatActivity() { private lateinit var mytxtview1: TextView private lateinit var mytxtview2: TextView private lateinit var progress: ProgressDialog override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mytxtview1 = findViewById(R.id.txt_view_1) mytxtview2 = findViewById(R.id.txt_view_2) progress = ProgressDialog(this).apply { setMessage("加载中...") show() } // 启动协程,绑定生命周期避免内存泄漏 lifecycleScope.launch { // 并行执行两个请求 val result1 = async { fetchData("url1") } val result2 = async { fetchData("url2") } // 等待两个请求都完成 val data1 = result1.await() val data2 = result2.await() // 更新UI mytxtview1.text = data1 mytxtview2.text = data2 if (progress.isShowing) progress.dismiss() } } // 挂起函数,在IO线程执行网络请求 private suspend fun fetchData(urlStr: String): String { return withContext(Dispatchers.IO) { val output = StringBuilder() try { val url = URL(urlStr) val connection = url.openConnection() as HttpURLConnection connection.requestMethod = "GET" val reader = BufferedReader(InputStreamReader(connection.inputStream)) var line: String? while (reader.readLine().also { line = it } != null) { output.append(line) } reader.close() connection.disconnect() } catch (e: Exception) { e.printStackTrace() return@withContext "请求失败:${e.message}" } output.toString() } } }
用OkHttp实现并行请求
先添加OkHttp依赖:
dependencies { implementation "com.squareup.okhttp3:okhttp:4.11.0" }
然后编写代码:
public class MyPublicClass extends AppCompatActivity { private TextView mytxtview1; private TextView mytxtview2; private ProgressDialog progress; private OkHttpClient client = new OkHttpClient(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mytxtview1 = findViewById(R.id.txt_view_1); mytxtview2 = findViewById(R.id.txt_view_2); progress = new ProgressDialog(this); progress.setMessage("加载中..."); progress.show(); // 第一个请求 Request request1 = new Request.Builder().url("url1").build(); client.newCall(request1).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { runOnUiThread(() -> { mytxtview1.setText("请求失败:" + e.getMessage()); checkIfAllDone(); }); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String data = response.body().string(); runOnUiThread(() -> { mytxtview1.setText(data); checkIfAllDone(); }); } else { runOnUiThread(() -> { mytxtview1.setText("请求失败:" + response.code()); checkIfAllDone(); }); } } }); // 第二个请求 Request request2 = new Request.Builder().url("url2").build(); client.newCall(request2).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { runOnUiThread(() -> { mytxtview2.setText("请求失败:" + e.getMessage()); checkIfAllDone(); }); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String data = response.body().string(); runOnUiThread(() -> { mytxtview2.setText(data); checkIfAllDone(); }); } else { runOnUiThread(() -> { mytxtview2.setText("请求失败:" + response.code()); checkIfAllDone(); }); } } }); } // 检查两个请求是否都完成,关闭进度条 private void checkIfAllDone() { if (!TextUtils.isEmpty(mytxtview1.getText()) && !TextUtils.isEmpty(mytxtview2.getText())) { if (progress.isShowing()) progress.dismiss(); } } }
必加的注意事项
- 网络权限:别忘了在
AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET" /> - UI线程限制:所有更新UI的操作必须在主线程执行,上述方案中已经通过
onPostExecute、lifecycleScope、runOnUiThread保证了这一点。
内容的提问来源于stack exchange,提问作者betty bth
相关产品推荐
相关产品推荐

