文件缓存与内存缓存

<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() {
		
		@Override
		public boolean handleMessage(Message msg) {
			switch (msg.what) {
			case LOAD_IMAGE_SUCCESS: //加载ok
				  LoadImageTask 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 = context;
		this.musics = musics;
		this.inflater = LayoutInflater.from(context);
		this.lvmusic=lvmusic;
		
		thread=new Thread(){	
			
			@Override
			public void run() {
				//在工作线程处理加载任务
				while(isLoop){//让他不断循环判断 类似handler的looper
				if(!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();
		
		
		
		
	}
	//获取bitmap
	protected 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;
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return musics.size();
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return musics.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	@Override
	public 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());
		
		
		
		//标记每个imageview
		String 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();
		}
		
	}
	
	
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值