Android Studio中HttpURLConnection加载网络图片报错问题求助
解决HttpURLConnection加载图片失败的问题
我帮你梳理几个关键问题,这些应该就是导致你持续报错的核心原因:
1. 主线程被阻塞的致命问题
你在download方法里调用了imageDownloader.execute(...).get(),get()方法会强制阻塞主线程直到异步任务完成,这完全违背了AsyncTask的设计初衷,不仅容易触发ANR(应用无响应),还会间接干扰网络请求的正常执行流程。
2. 多余的setDoOutput(true)设置
下载图片是纯粹的只读请求,根本不需要开启httpURLConnection.setDoOutput(true)——这个配置是用来向服务器发送数据(比如POST表单)的,开启它反而会干扰GET请求的正常逻辑。
3. Android 9+的明文HTTP限制
从Android 9(API 28)开始,系统默认禁止明文HTTP请求,你的图片URL是http://开头的,会被系统直接拦截,导致连接失败。
修复后的完整代码
package com.example.web; import androidx.appcompat.app.AppCompatActivity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.Toast; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class MainActivity extends AppCompatActivity { ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 提前初始化ImageView,不用每次点击都重复查找 imageView = findViewById(R.id.imageView3); } public class ImageDownloader extends AsyncTask<String, Void, Bitmap> { @Override protected Bitmap doInBackground(String... strings) { Bitmap bitmap = null; try { URL url = new URL(strings[0]); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); // 移除不必要的输出流配置 httpURLConnection.setDoInput(true); httpURLConnection.connect(); InputStream inputStream = httpURLConnection.getInputStream(); bitmap = BitmapFactory.decodeStream(inputStream); } catch (IOException e) { e.printStackTrace(); Log.e("ImageDownloadError", "下载失败原因: " + e.getMessage()); // 在主线程弹出错误提示 runOnUiThread(() -> Toast.makeText(MainActivity.this, "图片下载失败", Toast.LENGTH_SHORT).show()); } return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); // 这才是AsyncTask更新UI的正确姿势:在onPostExecute里操作主线程控件 if (bitmap != null) { imageView.setImageBitmap(bitmap); } else { // 下载失败可以设置一张本地占位图 imageView.setImageResource(R.drawable.ic_placeholder); } } } public void download(View view) { // 清除旧图片 imageView.setImageResource(0); ImageDownloader imageDownloader = new ImageDownloader(); // 只调用execute,绝对不要用get()阻塞主线程 imageDownloader.execute("http://upload.wikimedia.org/wikipedia/en/a/aa/Bart_Simpson_200px.png"); } }
解决明文HTTP限制的两种方案
方案一:允许特定域名的明文请求
在res/xml目录下新建network_security_config.xml文件:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">upload.wikimedia.org</domain> </domain-config> </network-security-config>
然后在AndroidManifest.xml的<application>标签中添加配置:
android:networkSecurityConfig="@xml/network_security_config"
方案二:改用HTTPS链接(更推荐)
直接把图片URL替换为HTTPS版本:https://upload.wikimedia.org/wikipedia/en/a/aa/Bart_Simpson_200px.png,维基媒体完全支持HTTPS,这是更安全合规的做法。
额外优化建议
- 避免重复调用
findViewById,在onCreate中初始化一次控件即可。 - 利用AsyncTask的
onPostExecute方法更新UI,这是Android异步任务更新UI的标准方式,能避免线程安全问题。 - 添加异常提示,让用户清晰知道下载失败的状态。
内容的提问来源于stack exchange,提问作者Graphics Engineer
相关产品推荐
相关产品推荐

