好多应用,像我们公司的《乘友》还有其他的《飞鸽》《陌陌》《啪啪》这些,几乎每一款应用都需要加载网络图片,那ToYueXinShangWan,这是比须熟练掌握的一个点,下面开始学习:

一、最简单加载网络图片

从网络上取图片数据,显示在应用中,简单不赘述:

        try {
URL url = new URL(path); //path图片的网络地址
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
if(httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK){
Bitmap bitmap = BitmapFactory.decodeStream(httpURLConnection.getInputStream());
imageview.setImageBitmap(bitmap);//加载到ImageView上
System.out.println("加载网络图片完成");
}else{
System.out.println("加载网络图片失败");
}
} catch (IOException e) {
e.printStackTrace();
}


二、轻量级异步加载图片

不会有人用第一种方法加载,连接网络和从网络取数据,花费部分时间,阻碍主线程,影响UI效果!

解决方案是:异步加载。先给ImageView设置一张图片,在异步任务中取数据,当从网络中取数据中和取数据失败时,就一直显示原来图片,当完成取数据时则再把新图片加载到ImageView上。

根据上面思路,就可以直接动手写了,为了便于代码复用,将加载图片写在一个工具类Utils中:

package com.lizhen.loadimage;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message; public class Utils {
public static void onLoadImage(final URL bitmapUrl,final OnLoadImageListener onLoadImageListener){
final Handler handler = new Handler(){
public void handleMessage(Message msg){
onLoadImageListener.OnLoadImage((Bitmap) msg.obj, null);
}
};
new Thread(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
URL imageUrl = bitmapUrl;
try {
HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
InputStream inputStream = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
Message msg = new Message();
msg.obj = bitmap;
handler.sendMessage(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }).start(); }
public interface OnLoadImageListener{
public void OnLoadImage(Bitmap bitmap,String bitmapPath);
}
}

然后在需要加载图片的地方调用调用onLoadImage()方法即可,在接口OnLoadImageListener的回调方法OnLoadImage()中,如:

   Utils.onLoadImage(url, new OnLoadImageListener() {
@Override
public void OnLoadImage(Bitmap bitmap, String bitmapPath) {
// TODO Auto-generated method stub
if(bitmap!=null){
imageview.setImageBitmap(bitmap);
}
}
});

wangluo jiazai zhong -->读取完网络数据后,加载图片效果---->
三、第二种方法的弊端是,当有大量图片需要加载时,会启动很多线程,避免出现这种情况的方法是,定义线程个数,当线程数达到最多时,不再开启,直到有一个线程结束,再开启一个线程;这种做法相当于

引入ExecutorService接口,于是代码可以优化如下:

在主线程中加入:private ExecutorService executorService = Executors.newFixedThreadPool(5);

在相应位置修改代码如下:

	executorService.submit(new Runnable(){

			@Override
public void run() {
// TODO Auto-generated method stub
URL imageUrl = bitmapUrl;
try {
System.out.println(Thread.currentThread().getName() + "线程被调用了。");
HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
InputStream inputStream = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
Message msg = new Message();
msg.obj = bitmap;
handler.sendMessage(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "线程结束。");
}
});


线程池大小为3,运行5个线程,我的输出结果为:

这里有关线程池的概念用法写在另一篇文章里!



四、关于方法二的改进,考虑到效率问题,可以引入缓存机制,把图片保留在本地,只需在线程run方法最后加上如下代码:

//缓存
if(Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)){
System.out.println("存在sd卡");
File cacheFile = new File(Environment.getExternalStorageDirectory()+"/cacheFile");
System.out.println(cacheFile.getPath());
if(!cacheFile.exists())
cacheFile.mkdir();
System.out.println(cacheFile.exists());
File imageCache = new File(cacheFile.getPath()+"/netwrok.png");
FileOutputStream fos = new FileOutputStream(imageCache);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bitmap.compress(Bitmap.CompressFormat.PNG, 80, bos);
bos.flush();
bos.close();
}


另一种把图片缓存在内存中使用如下步骤:

1、主线程 public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();

2、如果有缓存则读取缓存中数据,如果没有,则从网络获取数据;

//如果缓存过就从缓存中取出数据
        if (imageCache.containsKey(imageUrl)) {
            SoftReference<Drawable> softReference = imageCache.get(imageUrl);
            if (softReference.get() != null) {
                return softReference.get();//得到缓存中的Drawable
            }
        }

3、在网络获取数据时,不要忘记添加imageCache信息

imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));

注意:SoftReference<Drawable>就是用来处理解决大量图片下载内存溢出的问题的,还有Bitmap与Drawable之间的转换,在其他文章中将做总结!

2012 /11/18 1:26 太晚了,没想这问题会花费这么长时间;

 

最新文章

  1. Asp.net MVC 传递数据 从前台到后台,包括单个对象,多个对象,集合
  2. Microsoft Azure News(6) Azure新F系列虚拟机
  3. Atitit. 构造ast 语法树的总结attilax oao&#160;1. Ast结构树形12. ast view (自是个160k的jar )22.1. 多条语句ast结构22.2. 变量定义&#160;int&#160;b,c;&#160;的ast结构22.3. 方法调用meth1(a=1,b=2,c=3);&#160;&#160;的ast结构23. 误解的问题33.1. 语法书子能是个二叉树,实际上多叉树越好..33.2. 非要不个ast放到个s
  4. php get_class()函数
  5. *HDU1829 并查集
  6. PBS 安装
  7. 传递引用类型参数的两种方式(转自 MSDN)
  8. linux 文件权限除了r、w、x外还有s、t、i、a权限:
  9. flex mxmlc 手动编译项目
  10. G面经Prepare: Valid Preorder traversal serialized String
  11. 字符串匹配的KMP算法(转)
  12. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(1)-前言与目录(持续更新中...)
  13. MVC5个人用户账户身份验证集成google和facebook的OAuth2登陆
  14. python yield from 语法
  15. DesignPatternPrinciple(设计模式原则)二
  16. JenKins使用pm2部署.net core网站
  17. U813.0操作员功能权限和数据权限的设置
  18. jedis连接池参数minEvictableIdleTimeMillis和softMinEvictableIdleTimeMillis探索
  19. Ubuntu 14.04 LTS 系统空间不足,输入密码后,无法进入桌面的解决办法
  20. Windows编程的本质

热门文章

  1. 关于ContextImp的源码分析
  2. 用session设置访问权限
  3. mongodb学习(3)--- NodeJs使用mongoose操作mongodb
  4. webpack-dev-server 支持其他设备访问配置
  5. 上传相同文件名的时候不能触发change事件的解决方案
  6. bzoj 4310 跳蚤 二分答案+后缀数组/后缀树
  7. div两侧的boder断开 消失 奇怪
  8. bzoj 2115 [Wc2011] Xor 路径最大异或和 线性基
  9. Android下设置CPU核心数和频率
  10. [SaltStack] Crontab部署