资讯动态

高效加载大图(Android 官方培训课程中文版)

发布时间:2026/10/6 7:46:19 来源:尧图企业网站定制
文档教程移动开发【免费下载链接】android-training-course-in-chineseAndroid官方培训课程中文版项目地址https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese点击查看免费下载本仓库收录了 Android 官方培训课程的中文翻译其中graphics/displaying-bitmaps/目录专门讲解 Bitmap 的高效显示。本文以其中的 load-bitmap.md 为核心系统讲解如何在有限内存下加载缩小版图片从而避免OutOfMemory崩溃。读完本文你将掌握BitmapFactory.Options的inJustDecodeBounds与inSampleSize两项关键技术并拿到一套可直接复用的缩放采样加载代码。为什么要加载缩小版的图片图片有不同的形状与大小在大多数情况下它们的实际尺寸都比需要呈现的尺寸大很多。例如系统图库应用展示的是相机拍摄的照片而这类照片的分辨率通常远高于设备屏幕分辨率。Android 应用是在有限的内存下工作的理想情况是只需在内存中加载一个与目标 UI 控件尺寸相匹配的低分辨率照片。加载一张超过屏幕分辨率的高分辨率照片不仅没有显而易见的好处还会带来两个问题占用宝贵的内存资源容易触发java.lang.OutOfMemoryError在快速滑动图片如 ListView、GridView时产生额外的效率问题。关于 Bitmap 的内存消耗量级同目录的 index.md 给出了具体例证Galaxy Nexus 的相机可拍摄 2592×1936 像素约 5 MB的照片若使用 Android 2.3 起默认的ARGB_8888配置加载需要约 19 MB2592*1936*4字节内存会迅速耗尽应用的剩余内存。而 Android 设备对单个程序的内存限制往往是固定的通过ActivityManager.getMemoryClass()可查询当前设备上限详见 memory.md 中限制应用的内存一节。因此在真正解码之前先评估图片尺寸、按需降采样是 Bitmap 加载的第一步也是后续 缓存 Bitmap、非 UI 线程处理 Bitmap 等课程的基础。本课将介绍如何通过加载缩小版本的图片避免超出程序的内存限制。第一步读取位图的尺寸与类型Read Bitmap Dimensions and TypeBitmapFactory提供了一系列解码decode方法用于从不同的数据源创建 BitmapdecodeByteArray()从字节数组解码decodeFile()从文件路径解码decodeResource()从资源Resources解码以及decodeStream()等其它数据源方法。这些方法在构造位图时会尝试分配内存因此容易导致OutOfMemory异常。每一种解码方法都可以通过BitmapFactory.Options设置附加的解码选项。其中最关键的是inJustDecodeBounds属性设置为true时解码过程中不会分配内存此时 decode 方法返回一个null的 Bitmap但会把图片的真实尺寸与类型写入 Options 的outWidth、outHeight与outMimeType字段。借助这一技巧你可以在构造 Bitmap 之前优先读取图片的尺寸与类型。示例代码如下BitmapFactory.Options options new BitmapFactory.Options(); options.inJustDecodeBounds true; BitmapFactory.decodeResource(getResources(), R.id.myimage, options); int imageHeight options.outHeight; int imageWidth options.outWidth; String imageType options.outMimeType;实践建议为了避免java.lang.OutOfMemory异常应在真正解析图片之前检查它的尺寸——除非你能确定数据源提供的图片尺寸准确无误、且不会导致占用过多内存例如自己打包在 APK 内的小尺寸资源。第二步加载一个按比例缩小的版本到内存中Load a Scaled Down Version into Memory拿到图片尺寸后这些数据可以帮助我们决定应该加载完整图片还是加载缩小版本。决策时需要评估以下因素加载完整图片所需要耗费的内存程序在加载这张图片时可能涉及到的其他内存需求呈现这张图片的控件的尺寸大小如 ImageView 的实际尺寸屏幕大小与当前设备的屏幕密度。例如把一个 1024×768 像素的图片显示到 128×96 像素的 ImageView 上就没有必要把整张原图都加载到内存中。认识 inSampleSize为了告诉解码器加载缩小版本的图片需要在BitmapFactory.Options中设置inSampleSize的值。它的含义是采样率例如2048×1536 分辨率的图片设置inSampleSize为 4会产出一个大约 512×384 大小的 Bitmap按ARGB_8888配置每像素 4 字节计算加载这张缩小图仅需约 0.75 MB512*384*4字节而加载完整尺寸图片需要约 12 MB2048*1536*4字节。重要提示inSampleSize必须是 2 的幂。解码器对非 2 的幂的值会向下取整处理得到最接近的 2 的幂数详见inSampleSize官方文档。calculateInSampleSize按目标尺寸计算采样率下面的代码根据目标图片大小reqWidth、reqHeight计算合适的inSampleSizepublic static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height options.outHeight; final int width options.outWidth; int inSampleSize 1; if (height reqHeight || width reqWidth) { final int halfHeight height / 2; final int halfWidth width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) reqHeight (halfWidth / inSampleSize) reqWidth) { inSampleSize * 2; } } return inSampleSize; }这段算法的核心逻辑是从inSampleSize 1开始只要原图一半再除以当前采样率仍然大于目标宽高就把采样率翻倍最终返回的是既能满足目标尺寸、又尽可能小的 2 的幂值。这样可以保证缩放结果不小于目标控件尺寸避免被控件拉伸变糊同时把内存占用降到最低。decodeSampledBitmapFromResource两阶段解码的完整流程使用上面的方法需要遵循两阶段解码流程先设置inJustDecodeBounds true把 options 传给解码方法读取尺寸此阶段不分配内存根据尺寸计算inSampleSize设置inSampleSize的值并把inJustDecodeBounds设为false重新调用解码方法得到真正按比例缩小的 Bitmap。完整封装如下public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBoundstrue to check dimensions final BitmapFactory.Options options new BitmapFactory.Options(); options.inJustDecodeBounds true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds false; return BitmapFactory.decodeResource(res, resId, options); }使用这个方法可以简单加载任意大小的图片。下面的代码演示了加载一个接近100×100 像素的缩略图mImageView.setImageBitmap( decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));扩展从其它数据源解码上述方案同样适用于其它数据源——只需替换对应的BitmapFactory.decode*方法即可实现功能类似的解码函数从文件解码BitmapFactory.decodeFile(path, options)从字节数组解码BitmapFactory.decodeByteArray(bytes, offset, length, options)从输入流解码BitmapFactory.decodeStream(stream, outPadding, options)。在 manage-memory.md 的示例中官方示范了同样的模式decodeSampledBitmapFromFile(String filename, int reqWidth, int reqHeight, ImageCache cache)先以inJustDecodeBounds true解码读取尺寸再按需设置inSampleSize后二次解码。这印证了本文方法是全数据源通用的标准套路。与其它 Bitmap 优化课程的衔接load-bitmap.md是整个 高效显示 Bitmap 系列的第一课它解决的是如何省内存地加载单张图片。在真实应用中还需把本课方法与以下课程的技术组合使用非 UI 线程处理 Bitmap本课的decodeSampledBitmapFromResource涉及磁盘/解码 I/O耗时不可预估不应在 UI 线程执行。该课使用AsyncTaskWeakReference在后台线程解码并处理 ListView/GridView 复用视图带来的并发问题缓存 Bitmap使用LruCache内存缓存 DiskLruCache磁盘缓存避免滑出屏幕再滑回时重复解码管理 Bitmap 的内存使用在 Android 3.0 使用BitmapFactory.Options.inBitmap复用已分配内存在 Android 2.3.3 及以下谨慎使用recycle()在 UI 上显示 Bitmap综合以上所有技术在 ViewPager 与 GridView 中落地。补充decodeSampledBitmapFromResource只做尺寸缩放不做密度适配。若同一张图片要显示在不同密度的设备上可结合资源目录drawable-mdpi、drawable-hdpi等的屏幕适配机制见 supporting-devices/screens.md进一步控制加载成本。小结高效加载大图可以总结为一条核心流程先只读边界inJustDecodeBounds true不分配内存→ 依据目标控件尺寸计算 2 的幂采样率inSampleSize→ 二次解码得到缩小版 Bitmap。通过calculateInSampleSize与decodeSampledBitmapFromResource这两个工具方法可以在任何数据源上实现只加载够用的像素从源头控制 Bitmap 的内存占用避免OutOfMemoryError并为后续的异步加载、缓存复用打下基础。赞分享文档教程移动开发【免费下载链接】android-training-course-in-chineseAndroid官方培训课程中文版项目地址https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese点击查看免费下载相关推荐Android官方培训课程中文版教程Android官方培训课程中文版教程 1. 项目介绍 Android官方培训课程中文版Android Training Course in Chinese是文档教程移动开发YimMenu终极防护指南5步打造最安全的GTA5游戏体验YimMenu终极防护指南5步打造最安全的GTA5游戏体验 YimMenu是一款专为GTA5在线模式设计的开源辅助工具它不仅提供了丰富的游戏功能增强更重要逆向工程游戏开发Android 布局性能优化实战用 ViewStub 按需加载视图Android 官方培训课程中文版Android 布局性能优化实战用 ViewStub 按需加载视图Android 官方培训课程中文版 在 Android 应用中并非所有视图都需要在界面文档教程移动开发上一篇Windows Cleaner终极指南免费开源工具如何彻底解决C盘爆红问题下一篇MCP 安全最佳实践全指南基于 2026-07-28 规范的 mcp-for-beginners 安全防护体系创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑