这章就当填坑了,姑且也算是性能优化吧
⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄
0x00 集合处理
对一些list和数组的操作其实Java已经帮我们做了不少功课了,回想起来在一些使用场景中笔者还傻乎乎的写一堆for each (滑稽),这里就当提个醒。
场景一:
List和数组的转换,这个看官应该都很了解了,这里还是贴出来做下记录。
数组 → List Arrays.asList()
传入可变参数类型。例如
//一般写法
List<String> strList=Arrays.asList("1","2");
List<String> strList=Arrays.asList(new String[]{"1","2"});
值得一提的是这里有个隐藏的坑,上述写法是错误的,再用这个List的时候调用add,remove这些method时出现Java.lang.UnsupportedOperationException异常。这是由于Arrays.asList() 返回java.util.Arrays ArrayList,而不是ArrayList。Arrays ArrayList和ArrayList都是继承AbstractList,remove,add等method在AbstractList中是默认throw UnsupportedOperationException而且不作任何操作。ArrayList override这些method来对list进行操作,但是Arrays$ArrayList没有override remove(),add()等,所以会throw UnsupportedOperationException。
//正确写法
List<String> strList=new ArrayList<String>(Arrays.asList("1","2"));
List<String> strList=new ArrayList<String>(Arrays.asList(new String[]{"1","2"}));
场景二:
要快速填充默认数据的数组:
Arrays.fill();
例如
String strs=new String[10];
Arrays.fill(strs,"haha");
这样就能将tests的数组中都填充haha
这个字段,这个方法还支持起始位置和末了位置。
List同理Collections.fill()
场景三:
数组的排序看官也应该很熟悉了,值得一提的是,对数组进行Object排序时
Arrays.sort(Object[] objects,Comparator comparator)
一般是写个匿名实现类来完成排序,也可以重新在Bean对象中重写Comparable接口,对的你没看错,Comparable和Comparator 两个接口的区别在于Comparable是一个类需要内部实现,而Comparator 是外部调用的解析实现。2者都实现时sort方法优先外部调用,也就是Comparator 的compare,Comparator 和Comparable 的实现方法返回值含义相同,1排到后面,-1排到前面,0不变。
场景四:
求数组中某个value的index。好像终于可以摆脱自己for each的实现了,突然间就激动了起来呢。(滑稽)
Arrays.binarySearch()
传入数组和要查找的对象就可以了。对于实体bean的处理有几个点要注意下,
1.不像List集合重写equals
方法,执行indexOf
就能定位到索引,在binarySearch
的源码中的实现方式很不幸的发现不是依赖于equals
,而是基于二分查找和Comparable
来实现的。
核心方法:
public static int binarySearch(Object[] array, int startIndex, int endIndex, Object value) {
checkBinarySearchBounds(startIndex, endIndex, array.length);
int lo = startIndex;
int hi = endIndex - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
@SuppressWarnings("unchecked")
int midValCmp = ((Comparable) array[mid]).compareTo(value);
if (midValCmp < 0) {
lo = mid + 1;
} else if (midValCmp > 0) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
也就是说compareTo
返回0的时候才能定位到准确的位置,笔者这里认为,compareTo
去做一些equals
的活有点不太妥当。Arrays.binarySearch()
不过这个方法对于基本类型的索引还是值得一用的。
0x01 屏幕适配
这里补上笔者当初一个坑,
场景:
UI:开发我把图切好了,1x,2x,3x,够了吗(其实我是把给IOS的图顺便给你了)
我:够了够了,(我有dp约束,用一套不颗粒化就OK)
说完我就把2x的随手放到了drawable-hdpi里面,dp一约束,低分辨,中等分辨,高分辨一跑,OK收工,心中还窃喜,还给APK节省了点空间(^__^)
后来在一些新建的工程中研究控件的时候定位了到了这个问题,明明初始化只渲染一些背景图,Monitors 中显示占用内存100M+,最后笔者进行了一些测试
测试一:
ImageView控件,真机samsung S7,1440*2560,测试图片为真机截屏
放置路径 | wrap_content | 180dp*320dp | Glide加载 |
---|---|---|---|
drawable | 230.1 | 228.0 | 11.3 |
drawable-mdpi | 230.3 | 228.1 | 11.3 |
drawable-hdpi | 105.5 | 104.3 | 11.3 |
drawable-xhdpi | 60.7 | 62.2 | 11.2 |
drawable-xxhdpi | 28.9 | 30.8 | 11.3 |
drawable-xxxhdpi | 18.1 | 19.9 | 11.0 |
测试二:
ImageView控件,真机samsung S7,1440*2560,测试图片为小图标
放置路径 | 48px*48px | 128px*128px |
---|---|---|
drawable | 4.2 | 5.0 |
drawable-mdpi | 4.2 | 5.0 |
drawable-hdpi | 3.7 | 5.5 |
drawable-xhdpi | 4.3 | 5.3 |
drawable-xxhdpi | 4.3 | 5.1 |
drawable-xxxhdpi | 4.6 | 5.3 |
结论
对于大的图片例如启动界面,引导图片全屏图片,如果不用第三方图片框架加载一定要适配所有的drawable,以后内存溢出怎么死的都不知道。。小图标经笔者不完全测试不会有太大问题,虽然笔者更喜欢用svg,当然当path过于复杂则划不来了。
第二章暂时告一段落,如有错误,敬请指正!
敬畏耶和华是智慧的开端;认识至圣者便是聪明。 (箴言 9:10 和合本)