当需要用户选择图片的时候,可以调用系统相机或相册。如果需要用户进行多图选择就需要自定义图片选择器。这里介绍我自己封装的图片选择器。
实现思路
- 对外开放api的功能:多图选择,单张图片选择,可以设置,用户可以在外部配置图片加载器
- Android M以上进行权限处理
- 通过ContentResolver取到系统相册所有图片,并对其分类
- 用recycleview图片展示,可以进行相册文件夹选择,图片预览
实现代码
如何使用?
在Application中配置AlbumConfig
|
|
在Activity或Fragment中使用
|
|
核心实现类
- AlbumActivity:图片展示类
- ImageFolderDialog:图片文件夹展示类,用BottomSheetDialog实现
- ImagePreviewDialog:图片预览类
- AlbumConfig:Album配置类,可以配置图片显示列数,图片加载器
具体实现请自行查看代码。
碰到的问题
频繁滑动图片列表,一段时间后,界面会出现卡顿?
最开始我怀疑是由于某些对象的内存泄漏引起的,用Android studio的Memory Monitor分析,当我退出AlbumActivity界面时候,点击Initiate GC,内存又会回到正常状态,而且用Dump Java Heap生成的hprof执行内存泄漏分析,也没有发现有内存泄漏的对象。于是我开始觉得问题是由UIL加载图片引起的,查看了一下UIL打印出的日志,发现UIL几个问题:
- RecycleView中的第一次加载ImageView,UIL不能读取其宽高的,不过后面重用了后就能正常读取宽高了
- ImageView的layout_height如果设置为wrap_content,UIL也是不能读取其宽高
- 即使UIL设置了内存缓存,发现当频繁滑动列表的时候也会出现内存爆张的情况
解决:
- 加载图片的时候指定需要加载图片的宽高,指定的宽高一定别超过屏幕的宽高
new ImageSize(width,height)
; - 设置延迟加载
delayBeforeLoading(100)
- 设置图片像素格式
bitmapConfig(Bitmap.Config.RGB_565)
- 使用内部默认的线程池大小即可
ViewPager中展示很多图片的时候,左右滑动,在Memory Monitor上会发现内存一直在涨?
一开始初始化PagerAdapter的时候我会把ViewPager中的item view构造好,放入一个List中,然后直接使用,这样会造成即使ViewPager实际上只加载三张图片,但是其他的图片是在View中,这些view放在List中并没有被释放,导致滑动的时候内存话一直涨。
解决:
当需要显示该图片的时候,再构造view,不需要的时候从viewpager中移除view
|
|
总结
当我们写一个可能耗内存的功能时,最好能结合android studio的Memory Monitor进行测试,这样才能观测到你写的功能又没吃掉很多内存,如果在操作的过程出现内存一直上涨的情况,那就可能出现了内存泄漏或者出现了重复创建许多的大内存对象。分析工具可以用Android studio的Memory Monitor或者MAT工具。