Android 加载展示本地图片以及多点触控放大缩小展示图片
2015-12-16 12:18
330 查看
大家好,这是我的第一篇CSDN博客,以后有时间会给大家不断写关于Android技术的博客,希望大家喜欢。
加载图片时发生oom想必是每一位Android工程师都会遇到的并且很头疼的问题,那么今天我就来和大家聊聊如何高效加载本地图片并且怎么保证不出现oom。
实现界面如图:
首先介绍几个知识点:
1.LruCache :LruCache 通过key--value 键值对的形式存储数据,通过指定一个最大值来限制其内容的数量(LruCache<key,value>(int
maxSize)),每当一个value值被访问时移动到队列的头部,当LruCache中的value值达到上限时,再加入一个新的value,队尾的value将会被回收。LruCache核心原理是如果一个value长时间没有被使用那么这个value以后被使用的几率就会变小,即可以回收该value。
2.ExecutorService:线程池,同时有指定数量的线程在执行。
3.Semaphore:信号量机制,它负责协调各个线程,
以保证它们能够正确、合理的使用公共资源。在该项目中主要是保证在线程池中有正在执行的任务+准备执行的任务之和是一定的值。
4.异步加载图片以及图片的裁剪和旋转。
5.listview的优化。
好,下面咱们来看一下重要代码实现:
1.初始化LruCache:
2.加载bitmap:
4.优化listview:
重写OnScrollListener,在listview滚动时不加载图片,当其停止时加载可见项图片。
好的,今天就介绍到这里,项目地址下载地址:
源码下载地址
望各位同行加入 Android高级开发交流群 群号: 474440973 以便深入探讨
加载图片时发生oom想必是每一位Android工程师都会遇到的并且很头疼的问题,那么今天我就来和大家聊聊如何高效加载本地图片并且怎么保证不出现oom。
实现界面如图:
首先介绍几个知识点:
1.LruCache :LruCache 通过key--value 键值对的形式存储数据,通过指定一个最大值来限制其内容的数量(LruCache<key,value>(int
maxSize)),每当一个value值被访问时移动到队列的头部,当LruCache中的value值达到上限时,再加入一个新的value,队尾的value将会被回收。LruCache核心原理是如果一个value长时间没有被使用那么这个value以后被使用的几率就会变小,即可以回收该value。
2.ExecutorService:线程池,同时有指定数量的线程在执行。
3.Semaphore:信号量机制,它负责协调各个线程,
以保证它们能够正确、合理的使用公共资源。在该项目中主要是保证在线程池中有正在执行的任务+准备执行的任务之和是一定的值。
4.异步加载图片以及图片的裁剪和旋转。
5.listview的优化。
好,下面咱们来看一下重要代码实现:
1.初始化LruCache:
//得到当前应用<span style="color:#0820;">最大可用内存</span> int maxMemory = (int) Runtime.getRuntime().maxMemory(); //<font color="#0820">取其<font color="#0820">1/8作为<font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><font color="#0820"><span style="color:#0820;"><span style="color:#0820;"><span style="color:#0820;">LruCache</span></span></span></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font>的最大值</font></font> int cacheMemory = maxMemory / 8; mLruCache = new LruCache<String, Bitmap>(cacheMemory) { @Override protected int sizeOf(String key, Bitmap value) { //<span style="color:#0820;">当前bitmap<span style="color:#0820;">纵横字节乘积即是该对象<span style="color:#0820;">所占的内存空间</span></span></span> return value.getRowBytes() * value.getHeight(); } };
2.加载bitmap:
//通过控件的长度获取bitmap缩放比例 prviate ImageSize getImageViewSize(ImageView imageView) { ImageSize imageSize = new ImageSize(); LayoutParams mParams = imageView.getLayoutParams(); int width = imageView.getWidth(); if (width <= 0) { width = mParams.width; } if (width <= 0) { width = getImageViewFieldValue(imageView, "mMaxWidth"); } if (width <= 0) { width = imageView.getContext().getResources().getDisplayMetrics().widthPixels; } int height = imageView.getHeight(); if (height <= 0) { height = mParams.height; } if (height <= 0) { height = getImageViewFieldValue(imageView, "mMaxHeight"); } if (height <= 0) { height = imageView.getContext().getResources().getDisplayMetrics().heightPixels; } imageSize.width = width; imageSize.height = height; return imageSize; } /** * 根据图盘需要显示的宽和高对图片进行压缩 */ protected Bitmap decodeSampledBitmap(String path, int width, int height, int flag) { // 获取图片的宽和高,不把图片加载到内存中 BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); if (flag == 1) { options.inSampleSize = 1; } else { options.inSampleSize = caculateInSampleSize(options, width, height); } // 使用insampleSize再次解析图片 options.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeFile(path, options); int angle = readPictureDegree(path); return rotaingImageView(angle, bitmap); }3.获取图片角度及其旋转图片:
/** 得到图片旋转角度 */ private int readPictureDegree(String path) { int degree = 0; try { ExifInterface exifInterface = new ExifInterface(path); int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; } } catch (IOException e) { e.printStackTrace(); } return degree; } /** 旋转图片 */ private Bitmap rotaingImageView(int angle, Bitmap bitmap) { // 旋转图片 动作 Matrix matrix = new Matrix(); matrix.postRotate(angle); // 创建新的图片 Bitmap resizedBitmap = null; try { resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); } catch (Exception e) { // TODO: handle exception } bitmap = null; return resizedBitmap; }
4.优化listview:
重写OnScrollListener,在listview滚动时不加载图片,当其停止时加载可见项图片。
@Override public void onScrollStateChanged(AbsListView view, int scrollState) { currentScrollState = scrollState; if (currentScrollState == SCROLL_STATE_IDLE) { int visible = currentFirstVisibleItem; while (visible <= currentLastVisibleItem) { if (invisibleItem.contains(visible)) { if (null != mLisener) mLisener.loadItem(visible, visible - currentFirstVisibleItem); } visible++; } resetData(); } if (null != mLisener) { mLisener.onScrollStateChanged(view, scrollState); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (currentScrollState == SCROLL_STATE_FLING) { Speed isHigh = isHighSpeed(firstVisibleItem); if (isHigh == Speed.HIGHSPEED) { isCanLoadData = false; } else if (isHigh == Speed.LOWSPEED) { isCanLoadData = true; } } currentFirstVisibleItem = firstVisibleItem; currentLastVisibleItem = firstVisibleItem + visibleItemCount - 1; if (null != mLisener) { mLisener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); } }
好的,今天就介绍到这里,项目地址下载地址:
源码下载地址
望各位同行加入 Android高级开发交流群 群号: 474440973 以便深入探讨
相关文章推荐
- android图片颜色处理
- Android Listview item多种子布局实现方法详解
- 另类解决android中用三星手机拍的照片存储后旋转问题。
- Android编程之简单逐帧动画Frame的实现方法
- Android布局之RelativeLayout点滴
- 那些年Android开发中遇到的坑
- 那些年Android开发中遇到的坑
- Android5.0如何预置apk
- Android开发之使用AlertDialog创建对话框,单选框和多选框
- 下一代Android渠道打包工具
- (android:windowIsTranslucent)影响(android:windowAnimationStyle)Activity切换动画无效
- 【Android图片加载框架】制作自己的图片加载框架(一)
- 收集android上开源的酷炫的交互动画和视觉效果:Interactive-animation
- Android获取存储卡路径的方式
- Android编程中出现The connection to adb is down问题的解决方法
- android 设置边框只显示部分线条
- 《Android群英传》读书笔记(4)第五章:Android Scroll分析
- LayoutInflater和findViewById的区别
- android中 menu的属性详细解释
- 丢失Android系统库或者Conversion to Dalvik format failed with error 1错误的解决方法