当前位置: 代码迷 >> Android >> 教你怎么更省流量刷空间,微博-Android之异步加载网络图片
  详细解决方案

教你怎么更省流量刷空间,微博-Android之异步加载网络图片

热度:34   发布时间:2016-04-28 06:46:00.0
教你如何更省流量刷空间,微博---Android之异步加载网络图片

????? 朋友你是否有过这样的经历,当你刷空间,刷微博的时候,有的时候那些图片加载要很长时间,有的却直接可以看到无需慢慢等待,尤其是那些你已经刷过的内容,即使你处于断网的状态下也能看到,往往这种客户体验相对而言比较好,但是有的时候我们清理了手机的一些垃圾后,就不一样了,我们还得从新刷出来,下面我就要说说这个原理了。

????? 这所有的实现都是通过异步加载产生的,原理就是在我们运行软件时,我们需要将一些图片显示出来,那这些图片要从哪里获取呢,我们可以通过以下的方式获取,先看一张流程图:



?

?????? 首先我们先从map缓存中获取图片,map就是我们先前已经下载好的图片的集合,如果没有,我们查找图片文件,看是否有相应的文件,如果没有我们就开辟一个线程下载图片,等图片下载完成后,我们就将图片的url和图片放到map集合中。下一次再次刷新时,我们就直接从文件中读取已经存在的图片。到这里你应该知道如何更省流量得刷空间了吧,但是我们要实现这种功能额。下面我讲解一下核心代码:

?????? 首先我们创建这样一个类LazyImageLoader,类里面有下面的方法

public Bitmap get(String url,ImageLoaderCallback callback)	{				Bitmap bitmap = null;		//先看map集合众是否有这个url的图片		if(imgManger.contains(url))		{				//直接获取			bitmap = imgManger.getFromCache(url);			return bitmap;		}				else		{			callbackManager.put(url, callback);			//开启线程下载			startDownLoadTread(url);		}		//先返回一个默认的图片		return getDefaultImag(R.drawable.user_head);	}

?

???? ?首先我们先从map中查看是否有这个url的图片,如果有直接返回,如果没有开启线程下载,同时先返回一个固定的默认图片接下来我们就要看一下ImgManger中关于图片文件获取的主要方法了:

????? 首先我们新建一个map如下Map<String, SoftReference<Bitmap>>imgCache;至于SoftReference是什么,我就不说了,在这里主要是提高运行速度。

????? 首先我们先从上面定义的map中查找,代码如下:

public Bitmap getFromMapCache(String url)	{		Bitmap bitmap = null;				SoftReference<Bitmap> ref = null;				synchronized (this)		{			ref = imgCache.get(url);		}		if(null != ref)		{			bitmap = ref.get();					}		return bitmap;	}

?这里我们要注意防止线程同步的出现加关键词synchronized;

?????? 如果没有,我们再从查找文件,看是否存在,这里我遇到了一个问题,同时我也明白了一件经常看到的事,显然我们要下载的图片的url是如http://www.xxx/xxx.png这样的格式,那我们将下载的文件命名保存呢?如果我们直接以url保存,那最后是读取和保存的,如果我们重命名,那么首先我们要怎样才能确定保存的是独一无二的呢,其次读取时又要按先前对文件命名的规则对URL解析然后再获取图片,这样一来将会影响读取的速度,那解决办法是有的,通过使用加密算法对url直接加密生成一个独一无二的摘要即可,在这里我直接通过Md5进行加密,到这里你应该明白有时候我们看到的文件的名字是23d4c0e84e1e642088d184807e56e324,115d7b4284479089001c7962b2b906b1之类的吧。下面我们继续写代码:

public Bitmap getFromFile(String url)	{				String fileName = this.getMd5(url);				FileInputStream is=null;				try		{			is=context.openFileInput(fileName);						return BitmapFactory.decodeStream(is);		} 		catch (FileNotFoundException e)		{			e.printStackTrace();			return null;		}		finally		{			if(null != is)			{				try{is.close();}catch(Exception ex){};			}		}

??? 上面是直接从文件中查找图片,如果此时还没有,那么我们只有开启线程,通过线程来下载我们所需的图片,再将图片写到文件在写文件的时候文件名是也需要通过md5加密的。线程中主要的代码如下:

public Bitmap downloadImg(String urlStr) throws HttpException	{				try		{			URL url = new URL(urlStr);			HttpURLConnection connection =(HttpURLConnection) url.openConnection();						String fileName=writerToFile(urlStr,connection.getInputStream());						return BitmapFactory.decodeFile(fileName);					} 		catch (IOException e)		{			e.printStackTrace();		}				return null;	}

?上面是通过http从网络中获取数据,其中的writerToFile方法如下:

public String  writerToFile(String fileName, InputStream is)	{				BufferedInputStream bis = null;				BufferedOutputStream bos = null;				try		{			bis = new BufferedInputStream(is);			bos = new BufferedOutputStream(context.openFileOutput(MD5Utils.md5(fileName), Context.MODE_PRIVATE));						byte[] buffer = new byte[1024];			int length;						while((length = bis.read(buffer)) != -1)			{				bos.write(buffer, 0, length);			}					} catch (Exception e)		{					}		finally		{						try			{				if(null != bis)				{					bis.close();				}								if(null != bos)					{						bos.flush();						bos.close();										}							}			catch (IOException e)			{				e.printStackTrace();			}		}						return context.getFilesDir() + "/" + MD5Utils.md5(fileName);			}

?主要是快速读写文件的操作,挺简单的,不懂直接百度,最后当我们的文件写好了,再通过回调的方法
将图片显示出来就行了。下面是我写的小项目的测试,效果还是挺好的,


异步加载的源码我放在下面,稍微改一下
可以直接用,直接调用类SimpleImageLoader 中的showImg(ImageView view,String url);方法即可。
?

  相关解决方案