178.n1-三级缓存,使用自定义MyBitmapUtils,不使用xUtils的BitmapUtils加载图片

三级缓存机制:

内存缓存:优先加载,速度快,内存缓存中android给每一个app分配16m的内存。java中的引用是强引用,垃圾回收器不会回收。java中的引用默认都是强引用。软引用(SoftReference):java的垃圾回收机制会回收,内存不够的时候,垃圾回收器会考虑回收;弱引用(weakReference)在内存不够的时候,垃圾回收器会优先回收,虚引用(PhantomRefence)内存不够的时候,垃圾回收器会最先回收。

现在谷歌不推荐使用软引用,使用软引用缓存的时候,经常不是从内存中读取,而是从本地读取了,现在谷歌推荐使用LruCache来缓存,最少使用算法,哪一个使用的最少据回收哪一个,其将内存控制在一定的赌大小,超过这个大小会自动回收,这个大小是由开发者来设置。

sd卡(本地)缓存:次优先加载

网络缓存:最后考虑加载,速度慢,耗费流量,

图片的压缩处理

//图片压缩处理
BitmapFactory.Options option = new BitmapFactory.Options();
//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定
option.inSampleSize = 2;
//设置图片格式
option.inPreferredConfig = Bitmap.Config.RGB_565;
//获取到bitmap对象
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);

软引用的示例MyBitmapUtils.java

package com.ldw.beijing.utils.bitmap;

import android.graphics.Bitmap;
import android.widget.ImageView;

import com.ldw.beijing.R;

/*
 * 自定义图片加载工具
 */
public class MyBitmapUtils {
	
	//网络缓存
	NetCacheUtils mNetCacheUtils;
	//本地缓存
	LocalCacheUtils mLocalCacheUtils;
	//内存缓存
	MemoryCacheUtils mMemoryCacheUtils;
	
	//构造函数,一开始是从网络获取数据
	public MyBitmapUtils(){
		mMemoryCacheUtils = new MemoryCacheUtils();
		mLocalCacheUtils = new LocalCacheUtils();
		mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils, mMemoryCacheUtils);
		
	}

	public void display(ImageView iv_pic, String url) {
		
		System.out.println("url===" + url);
		System.out.println("iv_pic===" + iv_pic);
		
		// 设置默认加载图片
		iv_pic.setImageResource(R.drawable.news_pic_default);
		
		Bitmap bitmap = null;
		// 从内存读取
		bitmap = mMemoryCacheUtils.getBitmapFromMemory(url);
		//bitmap不是空,就从内存中读取图片
		if(bitmap != null){
			iv_pic.setImageBitmap(bitmap);
			System.out.println("从内存读取图片...");
			return;
		}
		
		//从本地读取
		bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
		//bitmap存在
		if (bitmap != null) {
			iv_pic.setImageBitmap(bitmap);
			System.out.println("从本地读取图片...");
			//将图片保存在内存
			mMemoryCacheUtils.setBitmapToMemory(url, bitmap);
			return;
		}
		//从网络读取
		mNetCacheUtils.getBitmapFromNet(iv_pic, url);
	}

}

三级缓存的示例

在PhotoMenuDetailPager.java中需要缓存图片,之前使用的是xUtils的BitmapUtils方法进行缓存的现在使用三级缓存,使用MyBitmapUtils作为接口来实现

package com.ldw.beijing.base.menudetails;

import java.util.ArrayList;

import android.app.Activity;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.gson.Gson;
import com.ldw.beijing.R;
import com.ldw.beijing.base.BaseMenuDetailPager;
import com.ldw.beijing.domain.PhotosData;
import com.ldw.beijing.domain.PhotosData.PhotoInfo;
import com.ldw.beijing.global.ClobalContants;
import com.ldw.beijing.utils.CacheUtils;
import com.ldw.beijing.utils.bitmap.MyBitmapUtils;
import com.lidroid.xutils.BitmapUtils;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest.HttpMethod;

/*
 * 菜单详情页-组图
*/ 
public class PhotoMenuDetailPager extends BaseMenuDetailPager {

	private ArrayList<PhotoInfo> mPhotoList;
	private PhotoAdapter mAdapter;
	private ImageButton btn_photo;
	private ListView lv_photo;
	private GridView gv_photo;
	public PhotoMenuDetailPager(Activity activity, ImageButton btn_photo) {
		super(activity);
		//获取到切换的对象
		this.btn_photo = btn_photo;
		btn_photo.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				// 按钮点击的时候切换展示方式
				changeDisplay();
				
			}
			
		});
	}

	@Override
	public View initView() {
		View view = View.inflate(mActivity, R.layout.menu_photo_pager, null);
		lv_photo = (ListView) view.findViewById(R.id.lv_photo);
		gv_photo = (GridView) view.findViewById(R.id.gv_photo);

		return view;
	}
	
	@Override
	public void initData() {
		//读取缓存
		String cache = CacheUtils
				.getCache(ClobalContants.PHOTOS_URL, mActivity);

		if (!TextUtils.isEmpty(cache)) {

		}
		//服务器中读取数据
		getDataFromServer();
	}
	
	private void getDataFromServer() {
		HttpUtils utils = new HttpUtils();
		utils.send(HttpMethod.GET, ClobalContants.PHOTOS_URL,
				new RequestCallBack<String>() {

					@Override
					public void onSuccess(ResponseInfo<String> responseInfo) {
						String result = (String) responseInfo.result;
						//解析json数据
						parseData(result);
						// 设置缓存
						CacheUtils.setCache(ClobalContants.PHOTOS_URL, result,
								mActivity);
					}

					@Override
					public void onFailure(HttpException error, String msg) {
						Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT)
								.show();
						error.printStackTrace();
					}
				});
	}

	//解析json数据
	protected void parseData(String result) {
		Gson gson = new Gson();
		PhotosData data = gson.fromJson(result, PhotosData.class);

		mPhotoList = data.data.news;// 获取组图列表集合

		if (mPhotoList != null) {
			mAdapter = new PhotoAdapter();
			lv_photo.setAdapter(mAdapter);
			gv_photo.setAdapter(mAdapter);
		
	}
		
	}

	class PhotoAdapter extends BaseAdapter{
		//private BitmapUtils utils;
		private MyBitmapUtils utils;
		//构造函数
		public PhotoAdapter() {
			utils = new MyBitmapUtils();
			/*
			utils = new BitmapUtils(mActivity);
			//默认加载图片
			utils.configDefaultLoadingImage(R.drawable.news_pic_default);
			*/
		}

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

		@Override
		public PhotoInfo getItem(int position) {
			// TODO Auto-generated method stub
			return mPhotoList.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) {
			ViewHolder holder;
			if (convertView == null) {
				convertView = View.inflate(mActivity, R.layout.list_photo_item,
						null);

				holder = new ViewHolder();
				holder.tv_title = (TextView) convertView
						.findViewById(R.id.tv_title);
				holder.iv_pic = (ImageView) convertView
						.findViewById(R.id.iv_pic);

				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}

			PhotoInfo item = getItem(position);
			//设置标题
			holder.tv_title.setText(item.title);
			//显示图片
			utils.display(holder.iv_pic, item.listimage);

			return convertView;
		}
		
	}
	
	static class ViewHolder {
		public TextView tv_title;
		public ImageView iv_pic;
	}
	
	// 是否是列表展示
	private boolean isListDisplay = true;
	
	/*
	 * 切换展现方式
	 */
	private void changeDisplay() {
		//当前是listView展示的时候需要切换到GridView展示
		if (isListDisplay) {
			isListDisplay = false;
			lv_photo.setVisibility(View.GONE);
			gv_photo.setVisibility(View.VISIBLE);
			//修改图标的样式
			btn_photo.setImageResource(R.drawable.icon_pic_list_type);

		} else {
			isListDisplay = true;
			lv_photo.setVisibility(View.VISIBLE);
			gv_photo.setVisibility(View.GONE);
			//修改图标的样式为GridView
			btn_photo.setImageResource(R.drawable.icon_pic_grid_type);
		}
	}

}

三级缓存的接口MyBitmapUtils.java,首先是考虑从内存中读取,然后考虑从本地,最后从网络

package com.ldw.beijing.utils.bitmap;

import android.graphics.Bitmap;
import android.widget.ImageView;

import com.ldw.beijing.R;

/*
 * 自定义图片加载工具
 */
public class MyBitmapUtils {

	//网络缓存
	NetCacheUtils mNetCacheUtils;
	//本地缓存
	LocalCacheUtils mLocalCacheUtils;
	//内存缓存
	MemoryCacheUtils mMemoryCacheUtils;
	
	//构造函数,一开始是从网络获取数据
	public MyBitmapUtils(){
		mMemoryCacheUtils = new MemoryCacheUtils();
		mLocalCacheUtils = new LocalCacheUtils();
		mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils, mMemoryCacheUtils);
		
	}

	public void display(ImageView iv_pic, String url) {
		
		System.out.println("url===" + url);
		System.out.println("iv_pic===" + iv_pic);
		
		// 设置默认加载图片
		iv_pic.setImageResource(R.drawable.news_pic_default);
		
		Bitmap bitmap = null;
		// 从内存读取
		bitmap = mMemoryCacheUtils.getBitmapFromMemory(url);
		//bitmap不是空,就从内存中读取图片
		if(bitmap != null){
			iv_pic.setImageBitmap(bitmap);
			System.out.println("从内存读取图片...");
			return;
		}
		
		//从本地读取
		bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
		//bitmap存在
		if (bitmap != null) {
			iv_pic.setImageBitmap(bitmap);
			System.out.println("从本地读取图片...");
			//将图片保存在内存
			mMemoryCacheUtils.setBitmapToMemory(url, bitmap);
			return;
		}
		//从网络读取
		mNetCacheUtils.getBitmapFromNet(iv_pic, url);
	}

}

网络缓存NetCacheUtils.java,图片加载的时候首先是从网络获取,然后再缓存在本地和内存中

package com.ldw.beijing.utils.bitmap;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;

/*
 * 网络缓存数据
 */
public class NetCacheUtils {
	
	private LocalCacheUtils mLocalCacheUtils;
	private MemoryCacheUtils mMemoryCacheUtils;

	public NetCacheUtils(LocalCacheUtils localCacheUtils, MemoryCacheUtils memoryCacheUtils) {
		mLocalCacheUtils = localCacheUtils;
		mMemoryCacheUtils = memoryCacheUtils;
	}
	/*
	 * 从网络加载图片,需要异步加载
	 */
	public void getBitmapFromNet(ImageView iv_pic, String url) {
		//开启AsyncTask,参数会在doInBackground中获取
		new BitmapTask().execute(iv_pic, url);
		
	}
	
	/*
	 * 异步加载,AsyncTask就是handler和线程池的封装
	 * 第一个泛型: 参数类型 第二个泛型: 更新进度的泛型, 第三个泛型是onPostExecute的返回结果
	 */
	class BitmapTask extends AsyncTask<Object, Void, Bitmap>{

		/*
		 * 后台的耗时方法,子线程中运行
		 */
		private ImageView iv_pic;
		private String url;

		@Override
		protected Bitmap doInBackground(Object... params) {
			//获取到传递的参数
			iv_pic = (ImageView) params[0];
			url = (String)params[1];
			
			// 将url和imageview绑定
			iv_pic.setTag(url);
			
			return downloadBitmap(url);
		}
		
		/*
		 * 更新进度,需要更新进度条, 主线程
		 */
		@Override
		protected void onProgressUpdate(Void... values) {
			super.onProgressUpdate(values);
		}
		
		/*
		 * 耗时方法结束以后,执行该方法,主线程中运行
		 */
		@Override
		protected void onPostExecute(Bitmap result){
			if (result != null) {
				//获取到和imageview绑定的url
				String bindUrl = (String) iv_pic.getTag();
				//判断绑定的url和当前的url是不是一致的
				if (url.equals(bindUrl)) {
					// 确保图片设定给了正确的imageview
					iv_pic.setImageBitmap(result);
					//图片下载完成以后往本地保存
					mLocalCacheUtils.setBitmapToLocal(url, result);// 将图片保存在本地
					//将图片内存缓存
					mMemoryCacheUtils.setBitmapToMemory(url, result);
					System.out.println("从网络缓存读取图片...");
				}
			}
		}
		
	}
	
	/*
	 * 下载图片
	 */
	private Bitmap downloadBitmap(String url) {
		HttpURLConnection conn = null;
		try {
			conn = (HttpURLConnection) new URL(url).openConnection();

			conn.setConnectTimeout(5000);
			conn.setReadTimeout(5000);
			conn.setRequestMethod("GET");
			conn.connect();

			int responseCode = conn.getResponseCode();
			if (responseCode == 200) {
				InputStream inputStream = conn.getInputStream();
				
				//图片压缩处理
				BitmapFactory.Options option = new BitmapFactory.Options();
				//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定
				option.inSampleSize = 2;
				//设置图片格式
				option.inPreferredConfig = Bitmap.Config.RGB_565;
				//获取到bitmap对象
				Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);
				return bitmap;
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//关闭流
			conn.disconnect();
		}

		return null;
	}

}

本地缓存LocalCacheUtils.java,本地缓存首先需要缓存在

package com.ldw.beijing.utils.bitmap;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import com.ldw.beijing.utils.MD5Encoder;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;

/*
 * 本地缓存
 */
public class LocalCacheUtils {
	
	//本地缓存的地址
	public static final String CACHE_PATH = Environment
			.getExternalStorageDirectory().getAbsolutePath() + "/news_cache_data";

	/*
	 * 从本地sdcard读图片
	 */
	public Bitmap getBitmapFromLocal(String url) {
		try {
			//得到图片url的md5值
			String fileName = MD5Encoder.encode(url);
			//创建一个文件夹
			File file = new File(CACHE_PATH, fileName);
			//判断文件夹是否存在
			if (file.exists()) {
				Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(
						file));
				return bitmap;
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}
	
	/*
	 * 向sdcard写图片,保存图片到sd卡
	 */
	public void setBitmapToLocal(String url, Bitmap bitmap) {
		try {
			//得到图片url的md5值
			String fileName = MD5Encoder.encode(url);
			//创建一个文件夹
			File file = new File(CACHE_PATH, fileName);
			//获取CACHE_PATH文件夹
			File parentFile = file.getParentFile();
			//判断CACHE_PATH是否存在 如果文件夹不存在, 创建文件夹
			if (!parentFile.exists()) {
				parentFile.mkdirs();
			}

			// 将图片保存在本地,第一个参数是格式,第二个是图片质量,第三个是图片路径
			bitmap.compress(CompressFormat.JPEG, 100,
					new FileOutputStream(file));
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}

内存中缓存MemoryCacheUtils.java使用LruCache实现

package com.ldw.beijing.utils.bitmap;

import java.lang.ref.SoftReference;
import java.util.HashMap;

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

/*
 * 内存缓存
 */
public class MemoryCacheUtils {

	private LruCache<String, Bitmap> mMemoryCache;

	public MemoryCacheUtils() {
		// 模拟器默认是16M,现在设定大小是2M
		long maxMemory = Runtime.getRuntime().maxMemory() / 8;
		mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
			//sizeOf用来获取图片占用的内存大小,默认是1个字节
			@Override
			protected int sizeOf(String key, Bitmap value) {
				// 获取图片占用内存大小
				int byteCount = value.getRowBytes() * value.getHeight();
				return byteCount;
			}
		};
	}

	/*
	 * 从内存读
	 */
	public Bitmap getBitmapFromMemory(String url) {
		return mMemoryCache.get(url);
	}

	/*
	 * 写内存
	 * */
	public void setBitmapToMemory(String url, Bitmap bitmap) {
		mMemoryCache.put(url, bitmap);
	}
	
	/*软引用的方法缓存
	//key-value的形式来保存图片缓存,使用SoftReference软引用来防止内存溢出
	private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new HashMap<String, SoftReference<Bitmap>>();
	//private HashMap<String, Bitmap> mMemoryCache = new HashMap<String, Bitmap>();这种容易内存溢出,图片不断的缓存
	//从内存中读取图片
	public Bitmap getBitmapFromMemory(String url) {
		//获取到软引用
		SoftReference<Bitmap> softReference = mMemoryCache.get(url);
		if (softReference != null) {
			Bitmap bitmap = softReference.get();
			return bitmap;
		}
		return null;
		
	}
	
	//网内存中写图片
	public void setBitmapToMemory(String url, Bitmap bitmap) {
		//使用软引用来写图片
		SoftReference<Bitmap> softReference = new SoftReference<Bitmap>(bitmap);
		mMemoryCache.put(url, softReference);
	}
	*/
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android xUtils3 是一个非常方便的 Android 开发工具包,其中包含了许多方便实用的功能,例如网络请求、图片加载等。下面是使用 xUtils3 获取网络图片的示例代码: 1. 在 build.gradle 中添加 xUtils3 的依赖: ```groovy dependencies { implementation 'org.xutils:xutils:3.5.0' } ``` 2. 在 AndroidManifest.xml 中添加网络权限: ```xml <uses-permission android:name="android.permission.INTERNET" /> ``` 3. 在代码中使用 xUtils3 获取网络图片: ```java ImageView imageView = findViewById(R.id.image_view); String imageUrl = "http://example.com/image.jpg"; x.image().bind(imageView, imageUrl, new Callback.CommonCallback<Drawable>() { @Override public void onSuccess(Drawable result) { // 图片加载成功 } @Override public void onError(Throwable ex, boolean isOnCallback) { // 图片加载失败 } @Override public void onCancelled(CancelledException cex) { // 图片加载被取消 } @Override public void onFinished() { // 图片加载完成 } }); ``` 上面的代码中,我们通过 x.image().bind() 方法来获取网络图片。第一个参数是 ImageView 对象,第二个参数是图片的 URL,第三个参数是一个 Callback,用于监听图片加载的状态。 其中,onSuccess() 方法表示图片加载成功,onError() 方法表示图片加载失败,onCancelled() 方法表示图片加载被取消,onFinished() 方法表示图片加载完成。在实际使用中,我们通常只需要实现 onSuccess() 方法即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值