分享一个安卓中异步获取网络图片并自适应大小的第三方程序(来自github)

安卓中获取网络图片,生成缓存

  用安卓手机,因为手机流量的限制,所以我们在做应用时,要尽量为用户考虑,尽量少耗点用户的流量,而在应用中网络图片的显示无疑是消耗流量最大的,所以我们可以采取压缩图片或者将图片进行缓存,使图片只需要获取一次即可。

获取网络图片,并进行压缩

public static Bitmap returnBitMapWego(String url) {
        URL myFileUrl = null;
        Bitmap bitmap = null;
        try {
            myFileUrl = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        try {
            HttpURLConnection conn = (HttpURLConnection) myFileUrl
                    .openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            Options op = new Options();
            op.inSampleSize = 2;//压缩的倍数
            op.inJustDecodeBounds = false;
            Rect rect = new Rect(0, 0, 0, 0);
            bitmap = BitmapFactory.decodeStream(is, rect, op);
            is.close();
        } catch (IOException e) {
            // e.printStackTrace();
            bitmap = null;

        }
        return bitmap;
    }

异步获取网络图片并进行缓存

package com.jijie.yibu;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.ConnectivityManager;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;

public class LogoLoader {

    public static final String CACHE_DIR = "/图片在手机中的保存路径";
    // 缓存下载过的图片的Map
    private Map<String, SoftReference<Bitmap>> caches;
    // 任务队列
    private List<Task> taskQueue;
    private boolean isRunning = false;
    private int width, height;
    private Context ctx;

    public LogoLoader(Context ctx) {this.ctx = ctx;
        // 初始化变量
        caches = new HashMap<String, SoftReference<Bitmap>>();
        taskQueue = new ArrayList<LogoLoader.Task>();
        // 启动图片下载线程
        isRunning = true;
        new Thread(runnable).start();
    }

    /**
     * 
     * @param imageView
     *            需要延迟加载图片的对象
     * @param url
     *            图片的URL地址
     * @param resId
     *            图片加载过程中显示的图片资源
     */
    public void showImageAsyn(ImageView imageView, String url, int resId) {
        imageView.setTag(url);
        Bitmap bitmap = loadImageAsyn(url, getImageCallback(imageView, resId));

        if (bitmap == null) {
            // imageView.setImageResource(resId);
            // imageView.setBackgroundResource(resId);
        } else {
            // imageView.setImageBitmap(bitmap);
            BitmapDrawable bd = new BitmapDrawable(bitmap);
            imageView.setBackgroundDrawable(bd);
        }
    }

    public Bitmap loadImageAsyn(String path, ImageCallback callback) {
        // 判断缓存中是否已经存在该图片
        if (caches.containsKey(path)) {
            // 取出软引用
            SoftReference<Bitmap> rf = caches.get(path);
            // 通过软引用,获取图片
            Bitmap bitmap = rf.get();
            // 如果该图片已经被释放,则将该path对应的键从Map中移除掉
            if (bitmap == null) {
                caches.remove(path);
            } else {
                // 如果图片未被释放,直接返回该图片

                return bitmap;
            }
        } else {
            // 如果缓存中不常在该图片,则创建图片下载任务
            Task task = new Task();
            task.path = path;
            task.callback = callback;

            if (!taskQueue.contains(task)) {
                taskQueue.add(task);
                // 唤醒任务下载队列
                synchronized (runnable) {
                    runnable.notify();
                }
            }
        }

        // 缓存中没有图片则返回null
        return null;
    }

    /**
     * 
     * @param imageView
     * @param resId
     *            图片加载完成前显示的图片资源ID
     * @return
     */
    private ImageCallback getImageCallback(final ImageView imageView,
            final int resId) {
        return new ImageCallback() {

            public void loadImage(String path, Bitmap bitmap) {
                if (path.equals(imageView.getTag().toString())) {
                    // imageView.setImageBitmap(bitmap);
                    BitmapDrawable bd = new BitmapDrawable(bitmap);
                    imageView.setBackgroundDrawable(bd);

                } else {
                    // imageView.setImageResource(resId);
                    // imageView.setBackgroundResource(resId);
                }
            }
        };
    }

    private Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            // 子线程中返回的下载完成的任务
            Task task = (Task) msg.obj;
            // 调用callback对象的loadImage方法,并将图片路径和图片回传给adapter
            task.callback.loadImage(task.path, task.bitmap);
        }

    };

    private Runnable runnable = new Runnable() {

        public void run() {
            while (isRunning) {
                // 当队列中还有未处理的任务时,执行下载任务
                while (taskQueue.size() > 0) {
                    // 获取第一个任务,并将之从任务队列中删除
                    Task task = taskQueue.remove(0);
                    // 将下载的图片添加到缓存

                    if (Environment.getExternalStorageState().equals(
                            Environment.MEDIA_MOUNTED)
                            && !checkNetWorkStatus()) {
                        File file = new File("/mnt/sdcard/jijie/imagecache/"
                                + getFileName(task.path));
                        if (file.exists() && file.length() > 100) {

                            try {
                                task.bitmap = PicUtil
                                        .getRoundedCornerBitmap(
                                                BitmapFactory
                                                        .decodeFile("/mnt/sdcard/jijie/imagecache/"
                                                                + getFileName(task.path)),
                                                10);

                            } catch (OutOfMemoryError err) {
                            }
                        }
                    } else if (checkNetWorkStatus()) {

                        task.bitmap = PicUtil.getRoundedCornerBitmap(
                                PicUtil.returnBitMap(task.path), 10);
                        try {
                            ByteArrayOutputStream baos = new ByteArrayOutputStream();

                            task.bitmap.compress(Bitmap.CompressFormat.PNG,
                                    100, baos);

                            Write(task.path, baos.toByteArray());
                        } catch (Exception e) {

                        }

                    }

                    // task.bitmap=PicUtil.getbitmapAndwrite(task.path);
                    // caches.put(task.path, new
                    // SoftReference<Bitmap>(task.bitmap));
                    if (handler != null) {
                        // 创建消息对象,并将完成的任务添加到消息对象中
                        Message msg = handler.obtainMessage();
                        msg.obj = task;
                        // 发送消息回主线程
                        handler.sendMessage(msg);
                    }
                }

                // 如果队列为空,则令线程等待
                synchronized (this) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    };

    // 回调接口
    public interface ImageCallback {
        void loadImage(String path, Bitmap bitmap);
    }

    class Task {
        // 下载任务的下载路径
        String path;
        // 下载的图片
        Bitmap bitmap;
        // 回调对象
        ImageCallback callback;

        @Override
        public boolean equals(Object o) {
            Task task = (Task) o;
            return task.path.equals(path);
        }
    }

    public void Write(String imageurl, byte[] b) {
        File cacheFile = FileUtil.getCacheFile(imageurl);

        BufferedOutputStream bos = null;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(cacheFile));

            bos.write(b, 0, b.length);
            bos.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static String getFileName(String path) {
        int index = path.lastIndexOf("/");
        return path.substring(index + 1);
    }

    private boolean checkNetWorkStatus() {
        boolean netSataus = false;
        ConnectivityManager cwjManager = (ConnectivityManager) ctx
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        cwjManager.getActiveNetworkInfo();
        if (cwjManager.getActiveNetworkInfo() != null) {
            netSataus = cwjManager.getActiveNetworkInfo().isAvailable();
        }
        return netSataus;
    }
}

  经过上面的代码虽然能够实现了图片的异步获取,自动缓存读取,图片压缩的功能,但是处理图片使图片适应控件大小还是比较让人头疼的问题,还有就是如果一起获取大量的网络的图片,会占用的非常多的内存,而且系统默认自由在界面销毁的时候才会释放,所以很容易遇到内存溢出的问题,下面向大家分享一个我在github上看到的一个处理网络的图片的程序。

能够实现异步获取图片,自动缓存读取,自动适应空间大小,而且完美解决内存溢出的问题

下面向大家展示一下:

以集街网(www.jijie.cc)中的一个图片为例,原图为:

<con.standopen.view.NetworkedCacheableImageView
        android:id="@+id/nciv_pug"
        android:layout_width="fill_parent"
        android:layout_height="100dip"
        android:scaleType="centerCrop" />

 <con.standopen.view.NetworkedCacheableImageView
        android:id="@+id/nciv_pug"
        android:layout_width="fill_parent"
        android:layout_height="300dip"
        android:scaleType="centerCrop" />

  <con.standopen.view.NetworkedCacheableImageView
        android:id="@+id/nciv_pug"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scaleType="centerCrop" />

  这分别是在不同大小的空间中显示同一张图片,能够看出来,代码只是将图片进行了剪切处理,避免拉伸变形,程序异步获取和自动缓存就不展示了,大家看代码就行的了。

工程文件(百度网盘):http://pan.baidu.com/s/1mguh2qc

github:https://github.com/yimengqingqiu/Android-Universal-Image-Loader

个人邮箱:standopen@foxmail.com(也可以发邮件给我索取)

 

 

posted @ 2013-12-27 21:57  StandOpen  阅读(1133)  评论(0编辑  收藏  举报