好多应用,像我们公司的《乘友》还有其他的《飞鸽》《陌陌》《啪啪》这些,几乎每一款应用都需要加载网络图片,那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 太晚了,没想这问题会花费这么长时间;

 

Android加载网络图片学习过程的更多相关文章

  1. Android加载网络图片报android.os.NetworkOnMainThreadException异常

    Android加载网络图片大致可以分为两种,低版本的和高版本的.低版本比如4.0一下或者更低版本的API直接利用Http就能实现了: 1.main.xml <?xml version=" ...

  2. android 加载网络图片

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  3. Android加载网络图片的工具类

    ImageView加载网络的图片 HttpUtil.java package com.eiice.httpuimagetils; import java.io.ByteArrayOutputStrea ...

  4. Android 加载网络图片设置到ImageView

    下载图片后显示在ImageView中 //1.定义全局变量 private Handler handler; private String image_url; private Bitmap bitm ...

  5. Android Volley入门到精通:使用Volley加载网络图片

    在上一篇文章中,我们了解了Volley到底是什么,以及它的基本用法.本篇文章中我们即将学习关于Volley更加高级的用法,如何你还没有看过我的上一篇文章的话,建议先去阅读Android Volley完 ...

  6. Android三种基本的加载网络图片方式(转)

    Android三种基本的加载网络图片方式,包括普通加载网络方式.用ImageLoader加载图片.用Volley加载图片. 1. [代码]普通加载网络方式 ? 1 2 3 4 5 6 7 8 9 10 ...

  7. android官方开源的高性能异步加载网络图片的Gridview例子

    这个是我在安卓安卓巴士上看到的资料,放到这儿共享下.这个例子android官方提供的,其中讲解了如何异步加载网络图片,以及在gridview中高效率的显示图片此代码很好的解决了加载大量图片时,报OOM ...

  8. Android中用双缓存技术,加载网络图片

    最近在学校参加一个比赛,写的一个Android应用,里面要加载大量的网络图片,可是用传统的方法图片一多就会造成程序出现内存溢出而崩溃.因为自己也在学习中,所以看了很多博客和视频,然后参照这些大神的写源 ...

  9. wemall app商城源码Android之ListView异步加载网络图片(优化缓存机制)

    wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享wemall app商城源码Android之L ...

随机推荐

  1. Java面试题之在多线程情况下,单例模式中懒汉和饿汉会有什么问题呢?

    懒汉模式和饿汉模式: public class Demo { //private static Single single = new Single();//饿汉模式 private static S ...

  2. docker 集群 flannel网络构建

    先保证集群状态是正常的 集群管理 kubelet 在创建pod 时会先下载一个pause 镜像,这个镜像用于容器基础网络管理非常重要: 每个node 节点都要执行该操作: iptables -P FO ...

  3. iOS工程中一天只让进行一次的操作如何做?

     转至: iosNSDateNSObject一天一次   整体思路:当进行操作的时候记录操作时间存在偏好设置当中,当再次点击的时候获取现在的时间然后和之前记录的时间进行比较.如果是一天那么就提示“今天 ...

  4. ASP.NET三层架构的优点和缺点

    原文发布时间为:2009-10-24 -- 来源于本人的百度文章 [由搬家工具导入] 小项目,以后变动不大的不用三层架构。 ASP.NET三层结构说明 完善的三层结构的要求是:修改表现层而不用修改逻辑 ...

  5. js2:事件的学习,弹出窗口,状态栏字改变,地图热点的使用

    原文发布时间为:2008-11-08 -- 来源于本人的百度文章 [由搬家工具导入] <html> <head> <title>js</title> & ...

  6. Linux Mint---安装篇

    先前接触过Debian6,埋头折腾已经是好几年前的事情了,后来就放下了,现在工作之余时间比较多,正好debian8.1出来了,于是乎装了个debian用,结果,自己其实还是一个菜蛋而已,连软件源怎么设 ...

  7. Windows下C++多线程同步与互斥简单运用(转)

    1.  互斥量,Mutex #include <Windows.h> #include <iostream> using namespace std; DWORD WINAPI ...

  8. hdu 3879 hdu 3917 构造最大权闭合图 俩经典题

    hdu3879  base station : 各一个无向图,点的权是负的,边的权是正的.自己建一个子图,使得获利最大. 一看,就感觉按最大密度子图的构想:选了边那么连接的俩端点必需选,于是就以边做点 ...

  9. PC网页js调用本地应用程序

    最近要现实一个在PC网页中实现点击按钮调用本地应用程序的功能 其实实现原理也非常简单, 首先注册一个本地注册表文件,指向本地应用程序路径 其次在网页中用js指向这个注册表文件,就可以实现网页调用本地应 ...

  10. IDEA - 设置所有文件编码为UTF-8格式

    问题一: File->Settings->Editor->File Encodings 问题二: File->Other Settings->Default Settin ...