Android上常见度量单位
px(像素):屏幕上的点,绝对长度,与硬件相关。
in(英寸):长度单位。
mm(毫米):长度单位。
pt(磅):1/72英寸,point。
dp(与密度无关的像素):一种基于屏幕密度的抽象单位。在每英寸160点的显示器上,1dp = 1px。
dip:Density-independent pixel,同dp相同。
sp:在dp的基础上,还与比例无关,个人理解为是一个矢量图形单位。
在xml中定义大小,建议TextView使用sp,其他使用dp
系统定义了四种像素密度:低(120dpi)、中(160dpi)、高(240dpi)和超高(320dpi)
设备独立像素转换成屏幕实际像素的换算很简单:px = dp * (dpi/ 160). pixls=160*(320/160)
ImageView中XML属性src和background的区别:
background会根据ImageView组件给定的长宽进行拉伸,而src就存放的是原图的大小,不会进行拉伸。src是图片内容(前景),bg是背景,可以同时使用。
此外:scaleType只对src起作用
Android资源文件
drawable-hdpi里面存放高分辨率的图片,如WVGA (480x800),FWVGA (480x854)
drawable-mdpi里面存放中等分辨率的图片,如HVGA (320x480)
drawable-ldpi里面存放低分辨率的图片,如QVGA (240x320)
Android手机屏幕标准 对应图标尺寸标准 屏幕密度
xhdpi 1280*720 96*96 320
hdpi 480*800 72*72 240
mdpi 480*320 48*48 160
ldpi 320*240 36*36 120
以480dip*800dip的WVGA(density=240)为例,详细列出不同density下屏幕分辨率信息:当density=120时 屏幕实际分辨率为240px*400px (两个点对应一个分辨率)
状态栏和标题栏高各19px或者25dip
横屏是屏幕宽度400px 或者800dip,工作区域高度211px或者480dip
竖屏时屏幕宽度240px或者480dip,工作区域高度381px或者775dip
density=160时 屏幕实际分辨率为320px*533px (3个点对应两个分辨率)
状态栏和标题栏高个25px或者25dip
横屏是屏幕宽度533px 或者800dip,工作区域高度295px或者480dip
竖屏时屏幕宽度320px或者480dip,工作区域高度508px或者775dip
density=240时 屏幕实际分辨率为480px*800px (一个点对于一个分辨率)
状态栏和标题栏高个38px或者25dip
横屏是屏幕宽度800px 或者800dip,工作区域高度442px或者480dip
竖屏时屏幕宽度480px或者480dip,工作区域高度762px或者775dip
如何计算密度(dpi)
1.标准是240*320画在1.5*2平方inch上。那么像每平方英寸有240*320/(1.5*2)=25600点,也就是一平方英寸的像素点为25600,所以dpi取为它的平方根160;如果你的dpi是120,那么它的密度就是0.75.
2. 密度不只是与width有关,还与height有关,所以不管width是1.8还是1.3,它的密度都有可能是1;比如width是1.8,只要它的 height是3/1.8的话,如果pixel为240*320的话,它的密度仍旧是1;同样如果width为1.3,只要它的 height为3/1.3的话,像素点为240*320,则密度也是1.
3.320*480/(1.5*2)得到单位平方英寸的点为51200,所以单位平方英寸是240*320画在1.5*2屏幕的2倍。但是这是平方英寸啊,算密度的时候要开平方的啊,所以应该是2开平方,是1.414吧,大致密度为1.5。
px与dip的关系
Android中,在160dpi (mdpi)中, 1 dip= 1 px;
以此类推,在120dpi(ldpi)中, 1 dip = 0.75px;
在240dpi (hdpi)中, 1 dip = 1.5px;
在320dpi(xhdpi)中, 1dip = 2px;
如何做到与密度无关
如果屏幕密度为160,这时dp和sp和px是一样的。1dp=1sp=1px,但如果使用px作单位,如果屏幕大小不变(假设还是3.2寸),而屏 幕密度变成了320。那么原来TextView的宽度设成160px,在密度为320的3.2 寸屏幕里看要比在密度为160的3.2寸屏幕上看短了一半。但如果设置成160dp或160sp的话。系统会自动将width属性值设置成320px的。 也就是160 * 320 / 160。其中320 / 160可称为密度比例因子。也就是说,如果使用dp和sp,系统会根据屏幕密度的变化自动进行转换。官方文档总结的计算公式为:pixels = dps * (density /160).
使用dip作为View的单位,这样就可以同时兼容各种不同的分辨率,不会造成UI的不可兼容。
优化的两种方式:
import android.content.Context; import android.util.DisplayMetrics; /** * 计算公式 pixels = dips * (density / 160) * * @version 1.0.1 2010-12-11 * * @author */ public class DensityUtil { private static final String TAG = DensityUtil.class.getSimpleName(); // 当前屏幕的densityDpi private static float dmDensityDpi = 0.0f; private static DisplayMetrics dm; private static float scale = 0.0f; /** * * 根据构造函数获得当前手机的屏幕系数 * * */ public DensityUtil(Context context) { // 获取当前屏幕 dm = new DisplayMetrics(); dm = context.getApplicationContext().getResources().getDisplayMetrics(); // 设置DensityDpi setDmDensityDpi(dm.densityDpi); // 密度因子 scale = getDmDensityDpi() / 160; Logger.i(TAG, toString()); } /** * 当前屏幕的density因子 * * @param DmDensity * @retrun DmDensity Getter * */ public static float getDmDensityDpi() { return dmDensityDpi; } /** * 当前屏幕的density因子 * * @param DmDensity * @retrun DmDensity Setter * */ public static void setDmDensityDpi(float dmDensityDpi) { DensityUtil.dmDensityDpi = dmDensityDpi; } /** * 密度转换像素 * */ public static int dip2px(float dipValue) { return (int) (dipValue * scale + 0.5f); } /** * 像素转换密度 * */ public int px2dip(float pxValue) { return (int) (pxValue / scale + 0.5f); } @Override public String toString() { return " dmDensityDpi:" + dmDensityDpi; } }
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> ... <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" /> ... </manifest>
参考http://blog.csdn.net/liguangzhenghi/article/details/7244271
http://www.oschina.net/question/234345_40079
http://uoloveruo.blog.163.com/blog/static/283311422011102304132611/
http://blog.csdn.net/xixinyan/article/details/7316313
http://download.csdn.net/detail/welovesunflower/4540688
http://www.360doc.com/content/12/0301/17/5087210_190881395.shtml
使用Memory Analyzer tool(MAT)分析内存泄漏(二)
http://www.blogjava.net/rosen/archive/2010/06/13/323522.html
MAT来分析,前提是Android开发和测试的工具安装完整,SDK,Eclipse:
1.打开Eclipse
2.选择 Help->Install New Software;
3.在Work with中添加站点:http://download.eclipse.org/mat/1.4/update-site/(这个地址可能会变化,但是新的地址可以在官方网站上找到:http://www.eclipse.org/mat/downloads.php )
4.生成.hprof文件:插入SD卡(Android机器很多程序都需要插入SD卡),并将设备连接到PC,在Eclipse中的DDMS中选择要测试的进程,然后点击Update Heap 和Dump HPROF file两个Button。
.hprof 文件会自动保存在SD卡上,把 .hprof 文件拷贝到PC上的\ android-sdk-windows\tools目录下。这个由DDMS生成的文件不能直接在MAT打开,需要转换。
运行cmd打开命令行,cd到\ android-sdk-windows\tools所在目录,并输入命令hprof-conv xxxxx.hprof yyyyy.hprof,其中xxxxx.hprof为原始文件,yyyyy.hprof为转换过后的文件。转换过后的文件自动放在android-sdk-windows\tools 目录下。
OK,到此为止,.hprof文件处理完毕,可以用来分析内存泄露情况了。
5.打开MAT:
在Eclipse中点击Windows->Open Perspective->Other->Memory Analysis
6.导入.hprof文件
在MAT中点击 File->Open File,浏览到刚刚转换而得到的.hprof文件,并Cancel掉自动生成报告,点击Dominator Tree,并按Package分组,选择自己所定义的Package 类点右键,在弹出菜单中选择List objects->With incoming references。
这时会列出所有可疑类,右键点击某一项,并选择Path to GC Roots->exclude weak/soft references,会进一步筛选出跟程序相关的所有有内存泄露的类。据此,可以追踪到代码中的某一个产生泄露的类。
Memory Analyzer 1.4.0 Release
- Version: 1.4.0.20140604 | Date: 25 June 2014 | Type: Released
- Update Site: http://download.eclipse.org/mat/1.4/update-site/
- Archived Update Site: MemoryAnalyzer-1.4.0.201406041413.zip (12 MB)
- Stand-alone Eclipse RCP Applications
Windows (x86) (52.4 MB)
Windows (x86_64) (52.4 MB)
Mac OSX (Mac/Cocoa x86) (52.0 MB)
Mac OSX (Mac/Cocoa x86_64) (51.8 MB)
Linux (x86/GTK 2) (52.3 MB)
Linux (x86_64/GTK 2) (52.4 MB)
Linux (PPC/GTK 2) (52.0 MB)
Linux (PPC64/GTK 2) (52.0 MB)
Linux (s390/GTK 2) (52.0 MB)
Linux (s390x/GTK 2) (52.0 MB)
Solaris 8 (x86/GTK 2) (51.8 MB)
Solaris 8 (SPARC/GTK 2) (51.9 MB)
HP-UX (IA64/GTK 2) (51.9 MB)
AIX (PPC/GTK 2) (52.4 MB)
AIX (PPC64/GTK 2) (52.5 MB)