用安卓手机,因为手机流量的限制,所以我们在做应用时,要尽量为用户考虑,尽量少耗点用户的流量,而在应用中网络图片的显示无疑是消耗流量最大的,所以我们可以采取压缩图片或者将图片进行缓存,使图片只需要获取一次即可。
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
个人邮箱:[email protected](也可以发邮件给我索取)