Java 从Internet获取图像并设置为ImageView

Java 从Internet获取图像并设置为ImageView,java,android,url,imageview,Java,Android,Url,Imageview,我有一个名为tab1的ImageView。我的代码看起来像这样 import java.io.InputStream; import java.net.URL; import android.app.Activity; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.widget.ImageView; import android.widget.TabHost; import

我有一个名为tab1的ImageView。我的代码看起来像这样

import java.io.InputStream;
import java.net.URL;

import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.Toast;

public class Paikallissaa extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    TabHost tabs = (TabHost) findViewById(R.id.tabhost);
    tabs.setup();   
    TabHost.TabSpec spec = tabs.newTabSpec("tag1");

    try {
        ImageView iv = (ImageView) findViewById(R.id.tab1);

        URL url = new URL("http://cdn.fmi.fi/weather-observations/products/finland/finland-weather-observations-map.png");
        InputStream content = (InputStream) url.getContent();
        Drawable d = Drawable.createFromStream(content, "src");

        iv.setImageDrawable(d);
    } catch (Exception e) {
        Toast.makeText(this, "Error getting image: " + e, Toast.LENGTH_SHORT);
    }

    spec.setContent(R.id.tab1);
    spec.setIndicator("Koko maa");
    tabs.addTab(spec);

    spec = tabs.newTabSpec("tag2");
    spec.setContent(R.id.tab2);
    spec.setIndicator("Raisio");
    tabs.addTab(spec);
}
}
(我讨厌代码块的东西…)


它不会更新图像。发生了什么?它一直显示我前面在main.xml中设置的图像

要从internet获取图像,请尝试以下操作:

HttpGet httpRequest = new HttpGet(URI.create("http://cdn.fmi.fi/weather-observations/products/finland/finland-weather-observations-map.png") );
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
bmp = BitmapFactory.decodeStream(bufHttpEntity.getContent());
ImageView iv = (ImageView) findViewById(R.id.tab1);
iv.setImageBitmat(bmp);
httpRequest.abort();

要从internet获取图像,请尝试以下操作:

HttpGet httpRequest = new HttpGet(URI.create("http://cdn.fmi.fi/weather-observations/products/finland/finland-weather-observations-map.png") );
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
bmp = BitmapFactory.decodeStream(bufHttpEntity.getContent());
ImageView iv = (ImageView) findViewById(R.id.tab1);
iv.setImageBitmat(bmp);
httpRequest.abort();

这将下载一个图像,并将其设置为图像视图,该视图取自我帮助编写的一个应用程序。我去掉了一些我正在使用的无用代码,但方法保持不变

public void setImage(){
    imageView.setImageURI(DownloadImage);
}

public String DownloadImage(){
    string filepath = DownloadFromUrl("url","filename.png");

}

public String DownloadFromUrl(String imageURL, String fileName) {

    File file = new File(PATH + fileName);
    try {
        URL url = new URL(imageURL);

        long startTime = System.currentTimeMillis();
        Log.d("ImageManager", "download begining");
        Log.d("ImageManager", "download url:" + url);
        Log.d("ImageManager", "downloaded file name:" + fileName);
        /* Open a connection to that URL. */
        URLConnection ucon = url.openConnection();

        /*
         * Define InputStreams to read from the URLConnection.
         */
        InputStream is = ucon.getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);

        /*
         * Read bytes to the Buffer until there is nothing more to read(-1).
         */
        ByteArrayBuffer baf = new ByteArrayBuffer(50);
        int current = 0;
        while ((current = bis.read()) != -1) {
            baf.append((byte) current);
        }

        /* Convert the Bytes read to a String. */
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(baf.toByteArray());
        fos.close();
        Log.d("ImageManager",
                "download ready in"
                        + ((System.currentTimeMillis() - startTime) / 1000)
                        + " sec");

    } catch (IOException e) {
        Log.d("ImageManager", "Error: " + e);
    }
    return file.toString();

}

这将下载一幅图像,并将其设置为图像视图,该视图取自我帮助编写的应用程序。我去掉了一些我正在使用的无用代码,但方法保持不变

public void setImage(){
    imageView.setImageURI(DownloadImage);
}

public String DownloadImage(){
    string filepath = DownloadFromUrl("url","filename.png");

}

public String DownloadFromUrl(String imageURL, String fileName) {

    File file = new File(PATH + fileName);
    try {
        URL url = new URL(imageURL);

        long startTime = System.currentTimeMillis();
        Log.d("ImageManager", "download begining");
        Log.d("ImageManager", "download url:" + url);
        Log.d("ImageManager", "downloaded file name:" + fileName);
        /* Open a connection to that URL. */
        URLConnection ucon = url.openConnection();

        /*
         * Define InputStreams to read from the URLConnection.
         */
        InputStream is = ucon.getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);

        /*
         * Read bytes to the Buffer until there is nothing more to read(-1).
         */
        ByteArrayBuffer baf = new ByteArrayBuffer(50);
        int current = 0;
        while ((current = bis.read()) != -1) {
            baf.append((byte) current);
        }

        /* Convert the Bytes read to a String. */
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(baf.toByteArray());
        fos.close();
        Log.d("ImageManager",
                "download ready in"
                        + ((System.currentTimeMillis() - startTime) / 1000)
                        + " sec");

    } catch (IOException e) {
        Log.d("ImageManager", "Error: " + e);
    }
    return file.toString();

}

为了做到这一点,我一直在使用一个助手类,我在互联网上找到了这个类,并对其进行了一些修改。它负责缓存图像并将图像加载到背景线程上

由于您的映像在服务器上发生了更改,您可能希望删除此代码的缓存部分

用法:

ImageLoader loader = new ImageLoader(this);
loader.DisplayImage(String.format(headshotUrl, data.Id), this, headshot);
这是:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Stack;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.widget.ImageView;

public class ImageLoader
{
    public static String TAG = "xxx";
    // the simplest in-memory cache implementation. This should be replaced with
    // something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
    private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>();

    private File cacheDir;

    public ImageLoader(Context context)
    {
        photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1);
        cacheDir = Utilities.GetCacheDir(context);
    }

    final int stub_id = R.drawable.face_placeholder;

    public void DisplayImage(String url, Activity activity, ImageView imageView)
    {
        imageView.setTag(url);
        Log.i(TAG, url);
        if (cache.containsKey(url))
            imageView.setImageBitmap(cache.get(url));
        else
        {
            queuePhoto(url, activity, imageView);
            imageView.setImageResource(stub_id);
        }
    }

    private void queuePhoto(String url, Activity activity, ImageView imageView)
    {
        // This ImageView may be used for other images before. So there may be
        // some old tasks in the queue. We need to discard them.
        photosQueue.Clean(imageView);
        PhotoToLoad p = new PhotoToLoad(url, imageView);
        synchronized (photosQueue.photosToLoad)
        {
            photosQueue.photosToLoad.push(p);
            photosQueue.photosToLoad.notifyAll();
        }

        // start thread if it's not started yet
        if (photoLoaderThread.getState() == Thread.State.NEW)
            photoLoaderThread.start();
    }

    private Bitmap getBitmap(String url)
    {
        // I identify images by hashcode. Not a perfect solution, good for the
        // demo.
        String filename = String.valueOf(url.hashCode());
        File f = new File(cacheDir, filename);

        // from SD cache
        Bitmap b = decodeFile(f);
        if (b != null)
            return b;

        // from web
        try
        {
            Bitmap bitmap = null;
            InputStream is = new URL(url).openStream();
            OutputStream os = new FileOutputStream(f);
            Utilities.CopyStream(is, os);
            os.close();
            bitmap = decodeFile(f);
            return bitmap;
        } catch (Exception ex)
        {
            ex.printStackTrace();
            return null;
        }
    }

    // decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File f)
    {
        try
        {
            // decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f), null, o);

            // Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE = 70;
            int width_tmp = o.outWidth, height_tmp = o.outHeight;
            int scale = 1;
            while (true)
            {
                if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
                    break;
                width_tmp /= 2;
                height_tmp /= 2;
                scale *= 2;
            }

            // decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        return null;
    }

    // Task for the queue
    private class PhotoToLoad
    {
        public String url;
        public ImageView imageView;

        public PhotoToLoad(String u, ImageView i)
        {
            url = u;
            imageView = i;
        }
    }

    PhotosQueue photosQueue = new PhotosQueue();

    public void stopThread()
    {
        photoLoaderThread.interrupt();
    }

    // stores list of photos to download
    class PhotosQueue
    {
        private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>();

        // removes all instances of this ImageView
        public void Clean(ImageView image)
        {
            for (int j = 0; j < photosToLoad.size();)
            {
                if (photosToLoad.get(j).imageView == image)
                    photosToLoad.remove(j);
                else
                    ++j;
            }
        };
    }

    class PhotosLoader extends Thread
    {
        public void run()
        {
            try
            {
                while (true)
                {
                    // thread waits until there are any images to load in the
                    // queue
                    if (photosQueue.photosToLoad.size() == 0)
                        synchronized (photosQueue.photosToLoad)
                        {
                            photosQueue.photosToLoad.wait();
                        }
                    if (photosQueue.photosToLoad.size() != 0)
                    {
                        PhotoToLoad photoToLoad;
                        synchronized (photosQueue.photosToLoad)
                        {
                            photoToLoad = photosQueue.photosToLoad.pop();
                        }
                        Bitmap bmp = getBitmap(photoToLoad.url);
                        cache.put(photoToLoad.url, bmp);
                        Object tag = photoToLoad.imageView.getTag();
                        if (tag != null && ((String) tag).equals(photoToLoad.url))
                        {
                            BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad.imageView);
                            Activity a = (Activity) photoToLoad.imageView.getContext();
                            a.runOnUiThread(bd);
                        }
                    }
                    if (Thread.interrupted())
                        break;
                }
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }

    PhotosLoader photoLoaderThread = new PhotosLoader();

    // Used to display bitmap in the UI thread
    class BitmapDisplayer implements Runnable
    {
        Bitmap bitmap;
        ImageView imageView;

        public BitmapDisplayer(Bitmap b, ImageView i)
        {
            bitmap = b;
            imageView = i;
        }

        public void run()
        {
            Log.i(TAG, "BitmapDisplayer run()");
            if (bitmap != null)
                imageView.setImageBitmap(bitmap);
            else
                imageView.setImageResource(stub_id);
        }
    }

    public void clearCache()
    {
        // clear memory cache
        cache.clear();

        // clear SD cache
        File[] files = cacheDir.listFiles();
        for (File f : files)
            f.delete();
    }

}
CopyStream功能:

public static void CopyStream(InputStream is, OutputStream os)
{
    final int buffer_size = 1024;
    try
    {
        byte[] bytes = new byte[buffer_size];
        for (;;)
        {
            int count = is.read(bytes, 0, buffer_size);
            if (count == -1)
                break;
            os.write(bytes, 0, count);
        }
    } catch (Exception ex)
    {
    }
}

为了做到这一点,我一直在使用一个助手类,我在互联网上找到了这个类,并对其进行了一些修改。它负责缓存图像并将图像加载到背景线程上

由于您的映像在服务器上发生了更改,您可能希望删除此代码的缓存部分

用法:

ImageLoader loader = new ImageLoader(this);
loader.DisplayImage(String.format(headshotUrl, data.Id), this, headshot);
这是:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Stack;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.widget.ImageView;

public class ImageLoader
{
    public static String TAG = "xxx";
    // the simplest in-memory cache implementation. This should be replaced with
    // something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
    private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>();

    private File cacheDir;

    public ImageLoader(Context context)
    {
        photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1);
        cacheDir = Utilities.GetCacheDir(context);
    }

    final int stub_id = R.drawable.face_placeholder;

    public void DisplayImage(String url, Activity activity, ImageView imageView)
    {
        imageView.setTag(url);
        Log.i(TAG, url);
        if (cache.containsKey(url))
            imageView.setImageBitmap(cache.get(url));
        else
        {
            queuePhoto(url, activity, imageView);
            imageView.setImageResource(stub_id);
        }
    }

    private void queuePhoto(String url, Activity activity, ImageView imageView)
    {
        // This ImageView may be used for other images before. So there may be
        // some old tasks in the queue. We need to discard them.
        photosQueue.Clean(imageView);
        PhotoToLoad p = new PhotoToLoad(url, imageView);
        synchronized (photosQueue.photosToLoad)
        {
            photosQueue.photosToLoad.push(p);
            photosQueue.photosToLoad.notifyAll();
        }

        // start thread if it's not started yet
        if (photoLoaderThread.getState() == Thread.State.NEW)
            photoLoaderThread.start();
    }

    private Bitmap getBitmap(String url)
    {
        // I identify images by hashcode. Not a perfect solution, good for the
        // demo.
        String filename = String.valueOf(url.hashCode());
        File f = new File(cacheDir, filename);

        // from SD cache
        Bitmap b = decodeFile(f);
        if (b != null)
            return b;

        // from web
        try
        {
            Bitmap bitmap = null;
            InputStream is = new URL(url).openStream();
            OutputStream os = new FileOutputStream(f);
            Utilities.CopyStream(is, os);
            os.close();
            bitmap = decodeFile(f);
            return bitmap;
        } catch (Exception ex)
        {
            ex.printStackTrace();
            return null;
        }
    }

    // decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File f)
    {
        try
        {
            // decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f), null, o);

            // Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE = 70;
            int width_tmp = o.outWidth, height_tmp = o.outHeight;
            int scale = 1;
            while (true)
            {
                if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
                    break;
                width_tmp /= 2;
                height_tmp /= 2;
                scale *= 2;
            }

            // decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        return null;
    }

    // Task for the queue
    private class PhotoToLoad
    {
        public String url;
        public ImageView imageView;

        public PhotoToLoad(String u, ImageView i)
        {
            url = u;
            imageView = i;
        }
    }

    PhotosQueue photosQueue = new PhotosQueue();

    public void stopThread()
    {
        photoLoaderThread.interrupt();
    }

    // stores list of photos to download
    class PhotosQueue
    {
        private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>();

        // removes all instances of this ImageView
        public void Clean(ImageView image)
        {
            for (int j = 0; j < photosToLoad.size();)
            {
                if (photosToLoad.get(j).imageView == image)
                    photosToLoad.remove(j);
                else
                    ++j;
            }
        };
    }

    class PhotosLoader extends Thread
    {
        public void run()
        {
            try
            {
                while (true)
                {
                    // thread waits until there are any images to load in the
                    // queue
                    if (photosQueue.photosToLoad.size() == 0)
                        synchronized (photosQueue.photosToLoad)
                        {
                            photosQueue.photosToLoad.wait();
                        }
                    if (photosQueue.photosToLoad.size() != 0)
                    {
                        PhotoToLoad photoToLoad;
                        synchronized (photosQueue.photosToLoad)
                        {
                            photoToLoad = photosQueue.photosToLoad.pop();
                        }
                        Bitmap bmp = getBitmap(photoToLoad.url);
                        cache.put(photoToLoad.url, bmp);
                        Object tag = photoToLoad.imageView.getTag();
                        if (tag != null && ((String) tag).equals(photoToLoad.url))
                        {
                            BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad.imageView);
                            Activity a = (Activity) photoToLoad.imageView.getContext();
                            a.runOnUiThread(bd);
                        }
                    }
                    if (Thread.interrupted())
                        break;
                }
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }

    PhotosLoader photoLoaderThread = new PhotosLoader();

    // Used to display bitmap in the UI thread
    class BitmapDisplayer implements Runnable
    {
        Bitmap bitmap;
        ImageView imageView;

        public BitmapDisplayer(Bitmap b, ImageView i)
        {
            bitmap = b;
            imageView = i;
        }

        public void run()
        {
            Log.i(TAG, "BitmapDisplayer run()");
            if (bitmap != null)
                imageView.setImageBitmap(bitmap);
            else
                imageView.setImageResource(stub_id);
        }
    }

    public void clearCache()
    {
        // clear memory cache
        cache.clear();

        // clear SD cache
        File[] files = cacheDir.listFiles();
        for (File f : files)
            f.delete();
    }

}
CopyStream功能:

public static void CopyStream(InputStream is, OutputStream os)
{
    final int buffer_size = 1024;
    try
    {
        byte[] bytes = new byte[buffer_size];
        for (;;)
        {
            int count = is.read(bytes, 0, buffer_size);
            if (count == -1)
                break;
            os.write(bytes, 0, count);
        }
    } catch (Exception ex)
    {
    }
}

最好的方法是先下载图像,保存它,然后将图像路径设置为图像视图。顺便问一下,您的日志中有哪些错误?图像大约每2-3次更改一次。下载多次好吗?或者你是什么意思?不,我没有任何错误。是的,如果你没有网络连接,你可以显示上次下载的图像。但是,这取决于您的用例。最好的方法是首先下载图像,保存它,然后将图像路径设置为图像视图。顺便问一下,您的日志中有哪些错误?图像大约每2-3次更改一次。下载多次好吗?或者你是什么意思?不,我没有任何错误。是的,如果你没有网络连接,你可以显示上次下载的图像。但是,这取决于您的用例。这可能有点复杂,但这可以防止UI线程被下载阻止,并允许在无法下载时使用占位符图像。您可以发布实用程序.CopyStream(InputStream,OutputStream)方法吗?我猜它与IOUtils.copy()相同@Adam我添加了复制流方法。除了图像很小:)是预期的还是我弄糟了什么?这可能有点复杂,但这可以防止UI线程被下载阻止,并允许在无法下载时使用占位符图像。你能发布Utilities.CopyStream吗(InputStream,OutputStream)方法?我猜它与IOUtils.copy()相同。Adam我添加了复制流方法。除了图像很小:)是预期的还是我弄糟了什么?