从URL加载图片

178

我有一个图片的URL,想要在ImageView中显示这张图片,但我无法做到。

如何实现这个功能呢?


1
可能是如何在Android中通过URL加载ImageView?的重复问题。 - blahdiblah
1
看看这些问题,重点关注第一个答案,你可以在这里找到两种简单完整的方法来实现:第一种方法(更完整)第二种方法(更简单) - lory105
1
你可以使用Picasso和Glide图像加载器,并将其显示到ImageView上。 - shweta c
17个回答

331

如果您是基于点击按钮加载图像,则上面的被接受答案非常好,但是如果您在新活动中执行此操作,则会使UI冻结一两秒钟。我发现使用简单的asynctask可以消除这个问题。

要使用asynctask,请将该类添加到您的活动末尾:

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
  ImageView bmImage;

  public DownloadImageTask(ImageView bmImage) {
      this.bmImage = bmImage;
  }

  protected Bitmap doInBackground(String... urls) {
      String urldisplay = urls[0];
      Bitmap mIcon11 = null;
      try {
        InputStream in = new java.net.URL(urldisplay).openStream();
        mIcon11 = BitmapFactory.decodeStream(in);
      } catch (Exception e) {
          Log.e("Error", e.getMessage());
          e.printStackTrace();
      }
      return mIcon11;
  }

  protected void onPostExecute(Bitmap result) {
      bmImage.setImageBitmap(result);
  }
}

并在您的onCreate()方法中使用以下代码进行调用:

new DownloadImageTask((ImageView) findViewById(R.id.imageView1))
        .execute(MY_URL_STRING);
不要忘记在你的清单文件中添加以下权限。
<uses-permission android:name="android.permission.INTERNET"/>

对我来说很好用。:)


2
我喜欢这个解决方案,你应该清理一下onPostExecute的代码,因为它的主体已经过时了。 - Sofija
这太棒了。@Sofija,你的清理是什么意思?如果有未知数量的图片怎么办? - 5er
@5er,我在原始答案中有一些括号放错了位置。我已经修正过了,所以你现在应该可以直接使用它。 - Kyle Clegg
不要忘记在清单中添加权限:<uses-permission android:name="android.permission.INTERNET"/> - mike20132013
1
这对于学习/破解非常棒(点赞),但是对于任何生产环境,您应该使用一个图像加载库,因为有很多选择。我最喜欢的是Universal Image Loader、Picasso等。 - AmeyaB
显示剩余4条评论

269
URL url = new URL("http://image10.bizrate-images.com/resize?sq=60&uid=2216744464");
Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
imageView.setImageBitmap(bmp);

65
你真的不应该使用那个,因为它会阻塞UI线程。这个库可以帮你处理线程和下载:https://github.com/koush/UrlImageViewHelper - koush
16
如果您在单独的线程上运行该代码块并去掉“setImageBitmap”函数,则不会设置图片。 - Jono
它正在工作,我正在缩略图中显示,并使用onclick imageview来显示dailog,但是它在10秒后才打开。 - Prasad
4
如果将这段代码包装在“AsyncTask”中,那就没问题了。 - Greg Brown
2
你应该在单独的线程中执行任何网络操作。当位图已经加载完成后,你可以使用ImageView.post()或Handler.post()。 - Volodymyr Shalashenko
请注意,在主线程或runOnUIThread()中调用BitmapFactory.decodeStream(url.openConnection().getInputStream())方法会导致android.os.NetworkOnMainThreadException异常。我使用了相同的代码,但是我创建了一个新线程并在其中运行它,这样就可以正常工作了。将位图图像设置到ImageView上需要在runOnUIThread()中实现。 - dkero

45

3
毕加索和Glide也是我的最爱。Glide的说法与毕加索非常相似,但缓存大小有很大改进。 - anhtuannd
1
这应该是新答案,虽然自己知道如何做总是很好。这篇伟大的文章解释了两种方法:https://medium.com/@crossphd/android-image-loading-from-a-string-url-6c8290b82c5e - Martin Jäkel
在性能方面,加载URL时使用Picasso还是Glide更好? - Prajwal Waingankar

12

有两种方式:

1)使用Glide库 这是从URL加载图像的最佳方式,因为当您尝试第二次显示相同的URL时,它将从缓存中显示,从而提高应用程序性能。

Glide.with(context).load("YourUrl").into(imageView);

依赖项:implementation 'com.github.bumptech.glide:glide:4.10.0'


2)使用流:在这里,您想从URL图像创建位图

URL url = new URL("YourUrl");
Bitmap bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
imageView.setImageBitmap(bitmap);

为了使用Glide,您还需要在Manifest.xml中添加此行: <uses-permission android:name="android.permission.INTERNET" /> 抱歉打扰了。我已经给您的答案点赞,因为Glide对我很有效。 - Tim
你的“catch”应该拼写为“cache”。 - Rawnak Yazdani

9
尝试这样做:添加Picasso库的jar文件。
Picasso.with(context)
                .load(ImageURL)
                .resize(width,height).noFade().into(imageView);

7
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;
import android.widget.Toast;

public class imageDownload {

    Bitmap bmImg;
    void downloadfile(String fileurl,ImageView img)
    {
        URL myfileurl =null;
        try
        {
            myfileurl= new URL(fileurl);

        }
        catch (MalformedURLException e)
        {

            e.printStackTrace();
        }

        try
        {
            HttpURLConnection conn= (HttpURLConnection)myfileurl.openConnection();
            conn.setDoInput(true);
            conn.connect();
            int length = conn.getContentLength();
            int[] bitmapData =new int[length];
            byte[] bitmapData2 =new byte[length];
            InputStream is = conn.getInputStream();
            BitmapFactory.Options options = new BitmapFactory.Options();

            bmImg = BitmapFactory.decodeStream(is,null,options);

            img.setImageBitmap(bmImg);

            //dialog.dismiss();
            } 
        catch(IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
//          Toast.makeText(PhotoRating.this, "Connection Problem. Try Again.", Toast.LENGTH_SHORT).show();
        }


    }


}

在你的活动中,取出ImageView并设置资源:imageDownload(url, yourImageview);


6
根据这个答案,我编写了自己的加载程序。
具有加载效果和出现效果:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;

import java.io.InputStream;

/**
 * Created by Sergey Shustikov (pandarium.shustikov@gmail.com) at 2015.
 */
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
{
    public static final int ANIMATION_DURATION = 250;
    private final ImageView mDestination, mFakeForError;
    private final String mUrl;
    private final ProgressBar mProgressBar;
    private Animation.AnimationListener mOutAnimationListener = new Animation.AnimationListener()
    {
        @Override
        public void onAnimationStart(Animation animation)
        {

        }

        @Override
        public void onAnimationEnd(Animation animation)
        {
            mProgressBar.setVisibility(View.GONE);
        }

        @Override
        public void onAnimationRepeat(Animation animation)
        {

        }
    };
    private Animation.AnimationListener mInAnimationListener = new Animation.AnimationListener()
    {
        @Override
        public void onAnimationStart(Animation animation)
        {
            if (isBitmapSet)
                mDestination.setVisibility(View.VISIBLE);
            else
                mFakeForError.setVisibility(View.VISIBLE);
        }

        @Override
        public void onAnimationEnd(Animation animation)
        {

        }

        @Override
        public void onAnimationRepeat(Animation animation)
        {

        }
    };
    private boolean isBitmapSet;

    public DownloadImageTask(Context context, ImageView destination, String url)
    {
        mDestination = destination;
        mUrl = url;
        ViewGroup parent = (ViewGroup) destination.getParent();
        mFakeForError = new ImageView(context);
        destination.setVisibility(View.GONE);
        FrameLayout layout = new FrameLayout(context);
        mProgressBar = new ProgressBar(context);
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.gravity = Gravity.CENTER;
        mProgressBar.setLayoutParams(params);
        FrameLayout.LayoutParams copy = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        copy.gravity = Gravity.CENTER;
        copy.width = dpToPx(48);
        copy.height = dpToPx(48);
        mFakeForError.setLayoutParams(copy);
        mFakeForError.setVisibility(View.GONE);
        mFakeForError.setImageResource(android.R.drawable.ic_menu_close_clear_cancel);
        layout.addView(mProgressBar);
        layout.addView(mFakeForError);
        mProgressBar.setIndeterminate(true);
        parent.addView(layout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    }

    protected Bitmap doInBackground(String... urls)
    {
        String urlDisplay = mUrl;
        Bitmap bitmap = null;
        try {
            InputStream in = new java.net.URL(urlDisplay).openStream();
            bitmap = BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return bitmap;
    }

    protected void onPostExecute(Bitmap result)
    {
        AlphaAnimation in = new AlphaAnimation(0f, 1f);
        AlphaAnimation out = new AlphaAnimation(1f, 0f);
        in.setDuration(ANIMATION_DURATION * 2);
        out.setDuration(ANIMATION_DURATION);
        out.setAnimationListener(mOutAnimationListener);
        in.setAnimationListener(mInAnimationListener);
        in.setStartOffset(ANIMATION_DURATION);
        if (result != null) {
            mDestination.setImageBitmap(result);
            isBitmapSet = true;
            mDestination.startAnimation(in);
        } else {
            mFakeForError.startAnimation(in);
        }
        mProgressBar.startAnimation(out);
    }
    public int dpToPx(int dp) {
        DisplayMetrics displayMetrics = mDestination.getContext().getResources().getDisplayMetrics();
        int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
        return px;
    }
}

添加权限
<uses-permission android:name="android.permission.INTERNET"/>

并执行:
 new DownloadImageTask(context, imageViewToLoad, urlToImage).execute();

干得好,Sergey。 - Alireza Jamali

5
在清单文件中添加网络权限
<uses-permission android:name="android.permission.INTERNET" />

请按照以下方式创建方法:
 public static Bitmap getBitmapFromURL(String src) {
    try {
        Log.e("src", src);
        URL url = new URL(src);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);
        Log.e("Bitmap", "returned");
        return myBitmap;
    } catch (IOException e) {
        e.printStackTrace();
        Log.e("Exception", e.getMessage());
        return null;
    }
}

现在在您的 onCreate 方法中添加以下内容:
 ImageView img_add = (ImageView) findViewById(R.id.img_add);


img_add.setImageBitmap(getBitmapFromURL("http://www.deepanelango.me/wpcontent/uploads/2017/06/noyyal1.jpg"));

这对我来说可行。


5
UrlImageViewHelper可以通过URL找到一张图片并将其填充到一个ImageView中。UrlImageViewHelper会自动下载、保存和缓存所有的图像URL BitmapDrawables。重复的URL不会被加载到内存两次。使用弱引用哈希表管理位图内存,因此一旦您不再使用图像,它就会被自动垃圾回收。
UrlImageViewHelper.setUrlDrawable(imageView, "http://example.com/image.png");

https://github.com/koush/UrlImageViewHelper


4
这是从URL显示图像的示例代码。
public static Void downloadfile(String fileurl, ImageView img) {
        Bitmap bmImg = null;
        URL myfileurl = null;
        try {
            myfileurl = new URL(fileurl);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        try {
            HttpURLConnection conn = (HttpURLConnection) myfileurl.openConnection();
            conn.setDoInput(true);
            conn.connect();
            int length = conn.getContentLength();
            if (length > 0) {
                int[] bitmapData = new int[length];
                byte[] bitmapData2 = new byte[length];
                InputStream is = conn.getInputStream();
                bmImg = BitmapFactory.decodeStream(is);
                img.setImageBitmap(bmImg);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接