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

来源:互联网 发布:构建开放数据生态圈 编辑:程序博客网 时间:2024/05/16 17:38

三级缓存机制:

内存缓存:优先加载,速度快,内存缓存中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(){@Overridepublic void onClick(View v) {// 按钮点击的时候切换展示方式changeDisplay();}});}@Overridepublic 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;}@Overridepublic 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>() {@Overridepublic void onSuccess(ResponseInfo<String> responseInfo) {String result = (String) responseInfo.result;//解析json数据parseData(result);// 设置缓存CacheUtils.setCache(ClobalContants.PHOTOS_URL, result,mActivity);}@Overridepublic 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);*/}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn mPhotoList.size();}@Overridepublic PhotoInfo getItem(int position) {// TODO Auto-generated method stubreturn mPhotoList.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic 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);//修改图标的样式为GridViewbtn_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;@Overrideprotected Bitmap doInBackground(Object... params) {//获取到传递的参数iv_pic = (ImageView) params[0];url = (String)params[1];// 将url和imageview绑定iv_pic.setTag(url);return downloadBitmap(url);}/* * 更新进度,需要更新进度条, 主线程 */@Overrideprotected void onProgressUpdate(Void... values) {super.onProgressUpdate(values);}/* * 耗时方法结束以后,执行该方法,主线程中运行 */@Overrideprotected void onPostExecute(Bitmap result){if (result != null) {//获取到和imageview绑定的urlString bindUrl = (String) iv_pic.getTag();//判断绑定的url和当前的url是不是一致的if (url.equals(bindUrl)) {// 确保图片设定给了正确的imageviewiv_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,现在设定大小是2Mlong maxMemory = Runtime.getRuntime().maxMemory() / 8;mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {//sizeOf用来获取图片占用的内存大小,默认是1个字节@Overrideprotected 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);}*/}


原创粉丝点击