Android加载网络图片学习过程

一、最简单加载网络图片

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

[java]  view plain copy
  1.       try {  
  2.     URL url = new URL(path); //path图片的网络地址  
  3.     HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();  
  4.     if(httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK){  
  5.         Bitmap bitmap  = BitmapFactory.decodeStream(httpURLConnection.getInputStream());  
  6.         imageview.setImageBitmap(bitmap);//加载到ImageView上  
  7.         System.out.println("加载网络图片完成");  
  8.     }else{  
  9.         System.out.println("加载网络图片失败");  
  10.     }  
  11. catch (IOException e) {  
  12.     e.printStackTrace();  
  13. }  

二、轻量级异步加载图片

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

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

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

[java]  view plain copy
  1. package com.lizhen.loadimage;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.net.HttpURLConnection;  
  6. import java.net.URL;  
  7.   
  8. import android.graphics.Bitmap;  
  9. import android.graphics.BitmapFactory;  
  10. import android.os.Handler;  
  11. import android.os.Message;  
  12.   
  13. public class Utils {  
  14.     public static void onLoadImage(final URL bitmapUrl,final OnLoadImageListener onLoadImageListener){  
  15.         final Handler handler = new Handler(){  
  16.             public void handleMessage(Message msg){  
  17.                 onLoadImageListener.OnLoadImage((Bitmap) msg.obj, null);  
  18.             }  
  19.     };  
  20.         new Thread(new Runnable(){  
  21.   
  22.             @Override  
  23.             public void run() {  
  24.                 // TODO Auto-generated method stub  
  25.                 URL imageUrl = bitmapUrl;  
  26.                 try {  
  27.                     HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();  
  28.                     InputStream inputStream = conn.getInputStream();  
  29.                     Bitmap bitmap = BitmapFactory.decodeStream(inputStream);  
  30.                     Message msg = new Message();  
  31.                     msg.obj = bitmap;  
  32.                     handler.sendMessage(msg);  
  33.                 } catch (IOException e) {  
  34.                     // TODO Auto-generated catch block  
  35.                     e.printStackTrace();  
  36.                 }  
  37.             }  
  38.               
  39.         }).start();  
  40.   
  41.     }  
  42.     public interface OnLoadImageListener{  
  43.         public void OnLoadImage(Bitmap bitmap,String bitmapPath);  
  44.     }  
  45. }  
然后在需要加载图片的地方调用调用onLoadImage()方法即可,在接口OnLoadImageListener的回调方法OnLoadImage()中,如:

[java]  view plain copy
  1.   Utils.onLoadImage(url, new OnLoadImageListener() {  
  2.     @Override  
  3.     public void OnLoadImage(Bitmap bitmap, String bitmapPath) {  
  4.         // TODO Auto-generated method stub  
  5.         if(bitmap!=null){  
  6.             imageview.setImageBitmap(bitmap);  
  7.         }  
  8.     }  
  9. });  
wangluo jiazai zhong --> 读取完网络数据后,加载图片效果---->
三、第二种方法的弊端是,当有大量图片需要加载时,会启动很多线程,避免出现这种情况的方法是,定义线程个数,当线程数达到最多时,不再开启,直到有一个线程结束,再开启一个线程;这种做法相当于

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

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

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

[java]  view plain copy
  1. executorService.submit(new Runnable(){  
  2.   
  3.         @Override  
  4.         public void run() {  
  5.             // TODO Auto-generated method stub  
  6.             URL imageUrl = bitmapUrl;  
  7.             try {  
  8.                  System.out.println(Thread.currentThread().getName() + "线程被调用了。");   
  9.                 HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();  
  10.                 InputStream inputStream = conn.getInputStream();  
  11.                 Bitmap bitmap = BitmapFactory.decodeStream(inputStream);  
  12.                 Message msg = new Message();  
  13.                 msg.obj = bitmap;  
  14.                 handler.sendMessage(msg);  
  15.             } catch (IOException e) {  
  16.                 // TODO Auto-generated catch block  
  17.                 e.printStackTrace();  
  18.             }  
  19.              System.out.println(Thread.currentThread().getName() + "线程结束。");   
  20.         }  
  21.     });  

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


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


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

[java]  view plain copy
  1. //缓存  
  2.                     if(Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)){  
  3.                         System.out.println("存在sd卡");  
  4.                         File cacheFile = new File(Environment.getExternalStorageDirectory()+"/cacheFile");  
  5.                         System.out.println(cacheFile.getPath());  
  6.                         if(!cacheFile.exists())  
  7.                             cacheFile.mkdir();  
  8.                         System.out.println(cacheFile.exists());  
  9.                         File imageCache = new File(cacheFile.getPath()+"/netwrok.png");  
  10.                         FileOutputStream fos = new FileOutputStream(imageCache);  
  11.                         BufferedOutputStream bos = new BufferedOutputStream(fos);    
  12.                         bitmap.compress(Bitmap.CompressFormat.PNG, 80, bos);     
  13.                         bos.flush();     
  14.                         bos.close();     
  15.                     }  

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

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之间的转换,在其他文章中将做总结

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值