您的位置:首页 > 其它

文件缓存与内存缓存

2016-08-05 19:49 267 查看
<strong><span style="font-size:24px;">1.java的引用类型:</span></strong>
<p style="border-width: 0px; padding-top: 0px; padding-bottom: 0px; margin-top: 0px; margin-bottom: 8px; list-style: none; text-indent: 2em; color: rgb(51, 51, 51); font-family: 宋体; font-size: 14px; line-height: 28px; background-color: rgb(249, 249, 249);">1)强引用(StrongReference)
    强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java<a target=_blank href="http://www.2cto.com/os/xuniji/" target="_blank" class="keylink" style="color: rgb(51, 51, 51); text-decoration: none;">虚拟机</a>宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
2)软引用(SoftReference)
    如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存(下文给出示例)。
    软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。</p><p style="border-width: 0px; padding-top: 0px; padding-bottom: 0px; margin-top: 0px; margin-bottom: 8px; list-style: none; text-indent: 2em; color: rgb(51, 51, 51); font-family: 宋体; font-size: 14px; line-height: 28px; background-color: rgb(249, 249, 249);">3) 弱引用(WeakReference)
    弱引用与软引用的区别在于:弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
    弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。</p><p style="border-width: 0px; padding-top: 0px; padding-bottom: 0px; margin-top: 0px; margin-bottom: 8px; list-style: none; text-indent: 2em; color: rgb(51, 51, 51); font-family: 宋体; font-size: 14px; line-height: 28px; background-color: rgb(249, 249, 249);"> 4)虚引用(PhantomReference)
    “虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。</p>----
软引用:
结合加载歌手图片来说明:
1.先创建一个MAP集合,用来保存图片的缓存文件
<pre name="code" class="html">	//内存缓存 使用软引用
private Map<String, SoftReference<Bitmap>> softcache=new HashMap<String, SoftReference<Bitmap>>();
2.使用时 先在获取到图片的Bitmap数据位置进行数据的放入缓存操作。
<span style="white-space:pre">	</span>//将获取的bitmap存入内存缓存
softcache.put(task.imagePath, new SoftReference<Bitmap>(bitmap));
3.缓存原理就是:如果文件在缓存中有,就直接从缓存中获取数据,由于是软引用,当系统内存不足时,内存回收机制GC就可能会销毁掉部分缓存数据,没有时,才需要重新加载图片数据。所以在adapter的getview中 先判断后、然后就可以直接使用控件加载bitmap数据
//先去内存缓存查看是否有此图的缓存图片
SoftReference<Bitmap> ref= softcache.get(path); //获取缓存中的缓存对象
if(ref!=null){
//从缓存对象中取出缓存图片
Bitmap b= ref.get();
if(b!=null){//有图
holder.ivImage.setImageBitmap(b); //直接加载内存的缓存的图片
Log.d("tedu", "从内存缓存读取。。");

return convertView ;//有则直接返回

}
}
<strong><span style="font-size:18px;">2.文件引用</span></strong>
文件引用就是将开始读取的数据放入app对应的缓存文件夹内,当下次读取时,就可以直接加载显示 节省流量。
1.先创建两个方法,一个是用于保存数据到缓存,一个是用于通过缓存文件路径去取出数据用于显示
<pre name="code" class="html">	//用于保存文件public static void saveMap(Bitmap bitmap,File file) throws FileNotFoundException{if(!file.getParentFile().exists()){//获取父目录文件夹是否存在,不存在就创建file.getParentFile().mkdirs();}//创建文件输出流 保存文件FileOutputStream fos=new FileOutputStream(file);//将bitmap文件压缩并输出bitmap.compress(CompressFormat.JPEG, 100, fos);}
<span style="white-space:pre">	</span>//用于获取数据的方法
<pre name="code" class="html">	public static Bitmap getBitmapByFile(File file){if(!file.exists()){return null;}//根据文件去找到文件缓存中的图片、Bitmap bitmap=BitmapFactory.decodeFile(file.getAbsolutePath());return bitmap;}
2.然后与软引用一样。在获取到数据的位置,调用保存方法,将数据放入缓存文件件夹内:
<pre name="code" class="html"><span style="white-space:pre">					</span>//将获取的图再存入文件缓存中String path=task.imagePath;//获取当前任务中的文件路径String filename=path.substring(path.lastIndexOf("/")+1);//不包含/File file=new File(context.getCacheDir(), "images/"+filename);//调用方法 保存文件BitMapUtil.saveMap(bitmap, file);
3.同样的方法,在getview中判断后 就可以直接使用控件进行数据的显示:
<span style="white-space:pre">		</span>//从文件中读取图片String filename=path.substring(path.lastIndexOf("/")+1);File file=new File(context.getCacheDir(),"images/"+filename);Bitmap map=BitMapUtil.getBitmapByFile(file);if(map!=null){holder.ivImage.setImageBitmap(map);Log.d("tedu", "从文件缓存读取。。");//从文件读时同时保存到内存缓存。加快读取速度softcache.put(path, new SoftReference<Bitmap>(map));return convertView;}
上面这段代码中,加了一句当从文件获取数据缓存数据时,重新将数据放入内存的缓存集合中 ,这样可以加快图片的显示,从内存中获取是最快的!
原码:
package com.wuxs.three_musicplayer_v4.Adapter;import java.io.File;import java.io.InputStream;import java.lang.ref.SoftReference;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import com.wuxs.three_musicplayer_v4.R;import com.wuxs.three_musicplayer_v4.entity.Music;import com.wuxs.three_musicplayer_v4.util.BitMapUtil;import com.wuxs.three_musicplayer_v4.util.MusicHttpUtil;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.ListView;import android.widget.TextView;public class MusicsAdapter extends BaseAdapter {private Context context;private List<Music> musics;private LayoutInflater inflater;private ListView lvmusic;// 为了获取标记的imageview//创建任务集合。private List<LoadImageTask> tasks=new ArrayList<LoadImageTask>();private Thread thread;private boolean isLoop=true;//内存缓存 使用软引用private Map<String, SoftReference<Bitmap>> softcache=new HashMap<String, SoftReference<Bitmap>>();private Handler handler=new Handler(new Handler.Callback() {@Overridepublic boolean handleMessage(Message msg) {switch (msg.what) {case LOAD_IMAGE_SUCCESS: //加载okLoadImageTask task= (LoadImageTask) msg.obj;Bitmap bitmap= task.bitmap; //数据ok//取出ImageView ivImage= (ImageView) lvmusic.findViewWithTag(task.imagePath);if(ivImage!=null){if(bitmap!=null){ivImage.setImageBitmap(bitmap);}}break;}return false;}});private static final int LOAD_IMAGE_SUCCESS=1;public MusicsAdapter(final Context context, List<Music> musics,ListView lvmusic) {super();this.context = conb633text;this.musics = musics;this.inflater = LayoutInflater.from(context);this.lvmusic=lvmusic;thread=new Thread(){@Overridepublic void run() {//在工作线程处理加载任务while(isLoop){//让他不断循环判断 类似handler的looperif(!tasks.isEmpty()){//如果任务集合不为空//获取bitmap数据LoadImageTask task=tasks.remove(0); //每次移除第一个任务出来//	Bitmap bitmap=getBitMap(task.imagePath);//改为采用压缩格式图片获取try {Bitmap bitmap = BitMapUtil.getYasuoPhoto(task.imagePath,40,40);//将bitmap数据封装进去task.bitmap=bitmap;//在这个位置获取了图片的bitmap信息 在此加上内存缓存//将获取的bitmap存入内存缓存softcache.put(task.imagePath, new SoftReference<Bitmap>(bitmap));//将获取的图再存入文件缓存中String path=task.imagePath;//获取当前任务中的文件路径String filename=path.substring(path.lastIndexOf("/")+1);//不包含/File file=new File(context.getCacheDir(), "images/"+filename);//调用方法 保存文件BitMapUtil.saveMap(bitmap, file);} catch (Exception e) {e.printStackTrace();}//发出消息Message mes=Message.obtain();mes.what=LOAD_IMAGE_SUCCESS;mes.obj=task;handler.sendMessage(mes);}else{//任务为空时 ,让线程休眠synchronized (thread) {try {thread.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}}};thread.start();}//获取bitmapprotected Bitmap getBitMap(String imagePath) {//调用方法try {String  url=imagePath;InputStream is= MusicHttpUtil.getXmlInputStream(url);Bitmap bitmap=BitmapFactory.decodeStream(is);//通过输入流获取图片bitmap数据return bitmap;} catch (Exception e) {e.printStackTrace();}return null;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn musics.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn musics.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {Music music=musics.get(position);viewHolder holder=null;if(convertView==null){convertView=inflater.inflate(R.layout.list_m, null);holder=new viewHolder();holder.ivImage=(ImageView) convertView.findViewById(R.id.ivphoto);holder.tvAuthor=(TextView) convertView.findViewById(R.id.tv_author);holder.tvTitle=(TextView) convertView.findViewById(R.id.tv_title);convertView.setTag(holder);}else {holder=(viewHolder) convertView.getTag();}holder.tvAuthor.setText(music.getAuthor());holder.tvTitle.setText(music.getTitle());//标记每个imageviewString path=music.getPic_small();holder.ivImage.setTag(path); //用small路径去标记imageview//先去内存缓存查看是否有此图的缓存图片SoftReference<Bitmap> ref= softcache.get(path); //获取缓存中的缓存对象if(ref!=null){//从缓存对象中取出缓存图片Bitmap b= ref.get();if(b!=null){//有图holder.ivImage.setImageBitmap(b); //直接加载内存的缓存的图片Log.d("tedu", "从内存缓存读取。。");return convertView ;//有则直接返回}}//从文件中读取图片String filename=path.substring(path.lastIndexOf("/")+1);File file=new File(context.getCacheDir(),"images/"+filename);Bitmap map=BitMapUtil.getBitmapByFile(file);if(map!=null){holder.ivImage.setImageBitmap(map);Log.d("tedu", "从文件缓存读取。。");//从文件读时同时保存到内存缓存。加快读取速度softcache.put(path, new SoftReference<Bitmap>(map));return convertView;}//没有则继续发任务 子线程中获取图片//在这里不能直接使用子线程来显示图片。应为那样会创建很多个线程、改为在构造方法时创建子线程。就会创建一个//在这里要做的事就是发出一个图片显示任务,然后给到子线程,去处理。LoadImageTask task=new LoadImageTask();task.imagePath=music.getPic_small(); //将路径设置进去//然后往集合里添加该task。 也就是发出了一个图片加载任务tasks.add(task);//唤醒休眠后的线程synchronized (thread) {thread.notify(); //唤醒线程}return convertView;}class viewHolder{ImageView ivImage;TextView tvTitle;TextView tvAuthor;}//设置任务属性private class LoadImageTask{private String  imagePath;private Bitmap bitmap;}//停止线程方法public void StopThread(){isLoop=false; //停止子线程//如果线程在休眠 就唤醒synchronized (thread) {thread.notify();}}}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内存 缓存