欢迎通过我的个人博客来查看此文章

老项目代码中发现有的图片放到了drawable中, 有的图片放到了mipmap中, 开发时秉承哪个目录下文件多放哪里的原则, 偶尔有疑惑搜一搜文章, 看到了结论也就这么使用了, 不过今日有时间, 依次检验了一下文章中的内容, 发现和实际的表现出入甚远.

常见的几种结论

Case 1 drawable会剔除其它密度, mipmap会保留全部(实际上最终的结论和这个有关联)

当xhdpi密度的手机在加载apk的时候Google是有一个优化的,是会剔除drawable其他密度的文件,只保留一个基本的drawable和drawable-xhdpi的文件,而mipmap是会全部保留的。

检测方法也比较简单, 在drawablemipmap不同密度的问价夹下分别放入同一类图片(图片标文字用于检查), 分别打包并检查其大小

Case1.1 安装包与应用大小

安装包大小 应用大小
drawable 13.3 MB (14,016,841 字节) 14.04MB
mipmap 13.3 MB (14,017,191 字节) 14.04MB
结论1.1

由此可见, 虽然两个安装包大小略有差异, 考虑到图片本身的大小(每张图片都在1Mb作用), 可以认为放入drawablemipmap文件夹中的图片在安装包和应用安装后没有差异

Case1.2 应用内表现

排除安装包的情况, 我们看一下在应用内的表现情况(通过adb shell wm density保证只修改手机的dpi信息)

100 420 800
drawable
mipmap
结论1.2

由此可见, 文件不论放在哪个目录下, 在手机中都会正确的显示为其匹配的图片资源

Case 1.3 应用内缩放

如果一个 imageView 有缩放动画,使用 drawable 下的图片,会一直使用一张来缩放图片实现 imageView 缩放动画。

如果使用 mipmap 下的图片,会根据缩放程度自动选择比当前分辨率大而又最接近当前分辨率的图片来做缩放处理。

这个可能大家见得不是很多, 不过既然有这种说法, 那就来测试一下

drawable
小缩放比例 大缩放比例
mipmap
小缩放比例 大缩放比例
结论1.3

可以看到在缩放动画的过程中, 一直显示的都是同一个动画

Case 2 应用内性能

Google对mipmap的图片进行了性能优化, 使其可以表现的更好

drawable
性能检查一览 MEMORY 10次图片加载平均时间
146
mipmap
性能检查一览 MEMORY 10次图片加载平均时间
151
结论2

可以看到, 加载单张图片的情况下其性能基本一致,不排除图片太小/太少性能优化不明显的情况, 不过尝试单证图片重复加载的情况下依旧表现为性能相近的情况, 或许时只针对特殊类型有优化? 如各位知道的更详细, 欢迎和我进行交流.

Case3 启动图标

在查阅资料的时候, 发现多次提及minmap应用只放入应用的启动图标, 使其可以得到优化.

100dpi 420dpi 800dpi
结论3

可以看到, 不同dpi的情况下应用图标的显示情况都是一致的. 其应用图标切换的边界值也是一致的.

关于420dpi和800dpi显示效果一样的情况, 因为种种原因, 应用图片在选择图片资源的时候, 需要将密度扩大25%左右[1].

看到这里大家应该和我有着一样的疑惑, 既然drawable和mipmap下图片的表现不论是安装包还是应用内, 甚至连官方文档都这么说了, 为什么各种测试结果下来, 两者的表现基本的一致呢?

罪魁祸首 Bundle(.aab)

提到Bundle(.aab)国内的开发者可能都比较陌生, 甚至不少之前做过Google Play上架应用的都不是很熟悉. 这个其实在我们每次手动打包的时候都会出现.



简单来说.aab包一般用于Google Play商店使用, 在你从Google Play商店下载应用时, 它会根据你手机的实际使用情况来下载不同drawable中的资源. 以期望达到减少安装包大小的目的. (一般情况下手机dpi不会改变, 其它密度下的资源文件直到应用卸载时都不会被使用).

下面的测试使用到的工具为bundletool[2], 简单来说, 就是模拟从Google Play下载应用和安装应用的过程.

安装包比较

安装包(apks)大小 应用大小
drawable 5.91 MB (6,201,543 字节) 6.22MB
mipmap 12.6 MB (13,230,670 字节) 13.26MB

应用内表现

100 420
drawable
mipmap
可以看到, 当图片放到drawable相关文件夹下的时候, 通过.aab包安装的应用会比放到minmap的下的应用小许多, 并且应用内更改dpi的时候页可以看到其不再能自动根据当前dpi选择对应的图片了.

结论

那么通过以上的测试, 我们可以得到以下结论了

以下结论均不涉及mipmap的性能优化相关(主要是暂未能设计好一个比较明确的测试对比)

以下测试机型为pixel 7, 测试Android版本为13

  1. 当应用构建为.apk的情况下, drawablemipmap文件夹下的资源表现无差异, 不论是应用内表现还是在启动器(应用图标)中表现.
  2. 当应用构建为.aab的情况下, drawable文件夹下的资源会寻找匹配的设备密度保留, 不匹配的资源会被删除已保证apk的大小.而mipmap文件夹下的资源文件会全部被保留.

那么我们应用内使用的图片就可以放到任意的目录下么?

如果你的应用是通过.apk分发安装的, 原则上是没有区别的. 但是Google对相关的目录也有推荐说明:

可以看到, mipmap目录下原则上只能保存应用图标. 同样, 其官方项目单密度资源项目也都是这样使用设计这两个文件夹的.

.aab包内mipmap保留机制是否是只适用于应用图标

测试后可以发现, mipmap的保留机制适用于mipmap下所有的图片资源, 不论是否为应用图标

相关代码可以访问我的GitHub


  1. https://developer.android.com/training/multiscreen/screendensities#mipmap

  2. https://github.com/google/bundletool/

Android中drawable和mipmap到底有什么区别的更多相关文章

  1. Android中Intent传值与Bundle传值的区别详解

    Android中Intent传值与Bundle传值的区别详解 举个例子我现在要从A界面跳转到B界面或者C界面   这样的话 我就需要写2个Intent如果你还要涉及的传值的话 你的Intent就要写两 ...

  2. android 中theme.xml与style.xml的区别

    from://http://liangoogle.iteye.com/blog/1848448 android 中theme.xml与style.xml的区别: 相同点: 两者的定义相同. <r ...

  3. Android中Drawable知识总结

    本文是学习<Android开发艺术探索>中Drawable章节之后的一个总结. 一.常见的Drawable种类介绍 Drawable类 xml标签 描述 BitmapDrawable 表示 ...

  4. Android中Drawable分类汇总(上)

    Android把可绘制的对象抽象为Drawable,不同的图形图像资源就代表着不同的drawable类型.Android FrameWork提供了一些具体的Drawable实现,通常在代码中都不会直接 ...

  5. [转]android中drawable资源的解释及例子

    原文链接:         http://blog.csdn.net/wode_dream/article/details/38584693 文章中的内容参考Dev Guide中的Drawable R ...

  6. android 中targetSdkVersion和与target属性的区别

    AndroidMenifest.xml中targetSdkVersion和project.properties中的target属性的区别      在AndroidMenifest.xml中,常常会有 ...

  7. Android 中pid与uid的作用与区别

    PID:为Process Identifier, PID就是各进程的身份标识. 程序一运行系统就会自动分配给进程一个独一无二的PID.进程中止后PID被系统回收,可能会被继续分配给新运行的程序,但是在 ...

  8. ANDROID 中UID与PID的作用与区别

    PID:为Process Identifier, PID就是各进程的身份标识,程序一运行系统就会自动分配给进程一个独一无二的PID.进程中止后PID被系统回收,可能会被继续分配给新运行的程序,但是在a ...

  9. [转] android 中 任务、进程和线程的区别

    PS: handler的目的是在组件进程中开辟一个线程作为消息的poller,收到消息后可以更新Activity中的控件(特殊的view) 任务.进程和线程     关于Android中的组件和应用, ...

  10. Android中UID和PID的作用和区别

    PID:为Process Identifier, PID就是各进程的身份标识,程序一运行系统就会自动分配给进程一个独一无二的PID.进程中止后PID被系统回收,可能会被继续分配给新运行的程序,但是在a ...

随机推荐

  1. py周结04

    py周结04 异常类型,理语法结构及实践案例 1.异常类型 SyntaxError 语法错误 NameError 名字错误 IndexError 指数错误 KeyError 关键字错误 Indenta ...

  2. 【基础语法规范】【函数式编程、字符串分割】BC6:输出输入的第二个整数

    思路:数组or字符串split分割 一.Scala 方法1:Int数组[不行] import scala.io.StdIn object Main{ def main(args:Array[Strin ...

  3. 【每日一题】【遍历orSet】2022年2月1日-NC66 两个链表的第一个公共结点

    描述输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空.(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的) 输入描述:输入分为是3段,第 ...

  4. 【云原生 • DevOps】一文掌握容器管理工具 Rancher

    一.容器管理工具 Rancher 介绍Rancher 是一个开源的企业级全栈化容器部署及管理平台,其实就是一个 Docker 的图形化管理界面.它为容器提供基础架构服务,可以让 CNI 兼容的网络服务 ...

  5. 什么是Auth模块?(全面了解)

    目录 一:Auth模块 1.什么是Auth模块? 2.Auth模块作用 二:引入Auth模块 1.其实我们在创建好一个Django项目之后直接执行数据库迁移命令会自动生成很多表 2.django在启动 ...

  6. Vue快速上门(3)-组件与复用

    VUE家族系列: Vue快速上门(1)-基础知识 Vue快速上门(2)-模板语法 Vue快速上门(3)-组件与复用 01.component组件 1.1.component基础知识 组件是可以复用的V ...

  7. ZooKeeper 3.6.X 配置参考

    "好记性不如烂笔头." -- 张溥 0x00 大纲 目录 0x00 大纲 0x01 前言 0x02 独立运行 0x03 集群运行 0x04 单机集群配置补充 0x05 官方原文 S ...

  8. JavaScript:函数:如何声明和调用函数?

    首先,理解什么是函数? 通俗的说,函数就是用大括号括起来的一组JS语句的集合体,是一个代码块,表达一种行为逻辑. 当我们调用函数的时候,我们就是在执行这一组JS语句. 然后,确定一点,在JS中,函数也 ...

  9. C++进阶(unordered_set+unordered_map模拟实现)

    unordered_set unordered_set是以无特定顺序存储唯一元素的容器,并且允许根据它们的值快速检索单个元素,是一种K模型. 在unordered_set中,元素的值同时是它的key, ...

  10. 本机无法配置远程服务器上的MySQL ODBC连接驱动

    1.问题描述 我想要访问远程windows服务器上的MySQL数据库,因此需要在本地ODBC驱动上配好远程服务器的MySQL.但配置好基本信息后,测试的时候出现如下问题: 2.解决方法 之所以产生这种 ...