You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:53:11