上篇博客讲到如何获取手机中所有歌曲的信息。本文就把上篇获取到的歌曲按照歌手名字分类。用一个ExpandableListView显示出来。

MainActivity .java

  1. public class MainActivity extends AppCompatActivity {
  2. private static List<MusicLoader.MusicInfo> musicList = new ArrayList<MusicLoader.MusicInfo>();
  3. private ExpandableListView groupLvSongs;
  4. @Override
  5. protected void onCreate(Bundle savedInstanceState) {
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.activity_main);
  8. initView();
  9. initEvent();
  10. }
  11. private void initEvent() {
  12. // 这是获取musicList,与本篇博客主题无关,大家只需要知道musicList代表所有歌曲,它的每一项都包含一首歌的所有信息
  13. musicList = MusicLoader.instance(getContentResolver()).getMusicList();
  14. // 设置适配器,给listview提供数据
  15. groupLvSongs.setAdapter(new myExadapter(MainActivity.this, musicList));
  16. }
  17. private void initView() {
  18. groupLvSongs = (ExpandableListView) findViewById(R.id.groupLvSongs);
  19. }
  20. /**
  21. * 按歌手分类的listview 对应的Adapter,自定义ExpandableListView的适配器
  22. * getGroupId()getChildId()hasStableIds()isChildSelectable暂时都默认自动生成的,
  23. * 最主要是getGroupView(),getChildView()方法
  24. */
  25. class myExadapter extends BaseExpandableListAdapter {
  26. //在获取view的时候需要context
  27. private Context context;
  28. //所有歌曲
  29. private List<MusicInfo> musicList = new ArrayList<MusicInfo>();
  30. //记录各个歌手名字
  31. private List<String> groupName = new ArrayList<String>();
  32. //按歌手名字分类后的所有歌曲
  33. private List<List<MusicInfo>> musicGroupBySinger = new ArrayList<List<MusicInfo>>();
  34. myExadapter(Context context, List<MusicInfo> group) {
  35. this.context = context;
  36. musicList = group;
  37. sortByArtistName();
  38. }
  39. // 根据歌手分类最终获得 musicGroupBySinger
  40. private void sortByArtistName() {
  41. // 第一个特殊
  42. groupName.add(musicList.get(0).getArtist());
  43. List<MusicInfo> musicListWithSameSinger = new ArrayList<MusicInfo>();
  44. musicListWithSameSinger.add(musicList.get(0));
  45. musicGroupBySinger.add(musicListWithSameSinger);
  46. for (int i = 1; i < musicList.size(); i++) {
  47. boolean flag = false;
  48. for (int j = 0; j < groupName.size(); j++) {
  49. // if该歌手名字已经存在
  50. if (musicList.get(i).getArtist().equals(groupName.get(j))) {
  51. flag = true;
  52. musicGroupBySinger.get(j).add(musicList.get(i));
  53. break;
  54. }
  55. }
  56. if (!flag) {
  57. groupName.add(musicList.get(i).getArtist());
  58. List<MusicInfo> musicListWithSameSinger2 = new ArrayList<MusicInfo>();
  59. musicListWithSameSinger2.add(musicList.get(i));
  60. musicGroupBySinger.add(musicListWithSameSinger2);
  61. }
  62. }
  63. }
  64. @Override
  65. public int getGroupCount() {
  66. return musicGroupBySinger.size();
  67. }
  68. @Override
  69. public int getChildrenCount(int groupPosition) {
  70. return musicGroupBySinger.get(groupPosition).size();
  71. }
  72. @Override
  73. public Object getGroup(int groupPosition) {
  74. return musicGroupBySinger.get(groupPosition);
  75. }
  76. @Override
  77. public Object getChild(int groupPosition, int childPosition) {
  78. return musicGroupBySinger.get(groupPosition).get(childPosition);
  79. }
  80. @Override
  81. public long getGroupId(int groupPosition) {
  82. return 0;
  83. }
  84. @Override
  85. public long getChildId(int groupPosition, int childPosition) {
  86. return 0;
  87. }
  88. //true还是false感觉没什么区别
  89. @Override
  90. public boolean hasStableIds() {
  91. return false;
  92. }
  93. //获取Group的视图
  94. @Override
  95. public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
  96. if (convertView == null) {
  97. LayoutInflater inflater = LayoutInflater.from(context);
  98. // R.layout.groups这个参数是group的视图
  99. convertView = inflater.inflate(R.layout.groups, null);
  100. }
  101. TextView title = (TextView) convertView.findViewById(R.id.tvSinger);
  102. title.setText(groupName.get(groupPosition));// 设置大组成员名称
  103. return convertView;
  104. }
  105. //获取展开的子视图
  106. /**
  107. * 在这里我有必要提一下listview加载视图的优化问题
  108. * <p/>
  109. * 一、复用convertView
  110. * 首先讲下ListView的原理:ListView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,
  111. * 返回的View就是这个Item显示的View。如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,
  112. * 创建View对象(mInflater.inflate(R.layout.lv_item, null);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。
  113. * Android提供了一个叫做Recycler(反复循环器)的构件,就是当ListView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,
  114. * 相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说如果能重用这个convertView,
  115. * 就会大大改善性能。
  116. * 所以getChildView 一开始会有一个判断语句
  117. * if (convertView == null) 如果不为空就直接使用之前那个。
  118. * <p/>
  119. * <p/>
  120. * 二、使用viewHolder类
  121. * 我们都知道在getView方法中的操作是这样的:
  122. * 先从xml中创建view对象(inflate操作,我们采用了重用convertView方法优化),然后在这个view去findViewById,
  123. * 找到每一个子View,如:一个TextView等。这里的findViewById操作是一个树查找过程,也是一个耗时的操作,所以这里也需要优化,
  124. * 就是使用viewHolder,把每一个子View都放在Holder中,当第一次创建convertView对象时,把这些子view找出来。
  125. * 然后用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。
  126. * 当第二次重用convertView时,只需从convertView中getTag取出来就可以。
  127. */
  128. @Override
  129. public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
  130. int position = musicList.indexOf(getChild(groupPosition,
  131. childPosition));
  132. // 优化listView
  133. ViewHolder viewHolder;
  134. if (convertView == null) {
  135. // R.layout.music_item是每一项的视图xml文件
  136. convertView = LayoutInflater.from(MainActivity.this).inflate(
  137. R.layout.music_item, null);
  138. TextView pTitle = (TextView) convertView
  139. .findViewById(R.id.title);
  140. viewHolder = new ViewHolder(pTitle);
  141. // 用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。
  142. convertView.setTag(viewHolder);
  143. } else {
  144. // 当第二次重用convertView时,只需从convertView中getTag取出来就可以。
  145. viewHolder = (ViewHolder) convertView.getTag();
  146. }
  147. viewHolder.title.setText(musicList.get(position).getTitle());
  148. return convertView;
  149. }
  150. @Override
  151. public boolean isChildSelectable(int groupPosition, int childPosition) {
  152. return false;
  153. }
  154. }
  155. class ViewHolder {
  156. TextView title;
  157. public ViewHolder(TextView pTitle) {
  158. title = pTitle;
  159. }
  160. }
  161. }

成果展示:

使用ExpandableListView以及如何优化view的显示减少内存占用相关推荐

  1. 怎么优化GO语言服务的内存占用

    内存优化: 1.小对象合并成结构体一次分配,减少内存分配次数 2. 缓存区内容一次分配足够大小空间,并适当复用 3.slice和map采make创建时,预估大小指定容量 4.长调用栈避免申请较多的临时 ...

  2. UE 手游在 iOS 平台运行时内存占用太高?试试这样着手优化

    性能优化,对游戏开发来说是一个需要不断钻研的课题,性能越好,游戏才会运行的更加顺畅,玩家的体验感才会更好.腾讯游戏学院专家.游戏客户端开发 Leonn,将和大家分享 UE 手游在 iOS 平台上的内存 ...

  3. redis占用内存过低_使用多种数据结构优化Redis 内存占用

    背景 广告平台 adx 在处理曝光/点击上报时,使用 redis 的 setnx 命令去重,其逻辑如下 构造一个形如 s:track:%d:%s:%s 的 key,参数分别是上报类型(曝光 or 点击 ...

  4. 优化SQL Server的内存占用之执行缓存

    优化SQL Server的内存占用之执行缓存篇 优化SQL Server的内存占用之执行缓存 在论坛上常见有朋友抱怨,说SQL Server太吃内存了.这里笔者根据经验简单介绍一下内存相关的调优知识. ...

  5. 【华为云技术分享】五个Taurus垃圾回收compactor优化方案,减少系统资源占用

    TaurusDB是一种基于MySQL的计算与存储分离架构的云原生数据库,一个集群中包含多个存储几点,每个存储节点包含多块磁盘,每块磁盘对应一个或者多个slicestore的内存逻辑结构来管理. 在ta ...

  6. arcgis前端(3)----->基础篇--自定义地图优化/隐藏or显示子图层

    arcgis前端(3)----->基础篇–自定义地图优化/隐藏or显示子图层 文章目录 arcgis前端(3)----->基础篇--自定义地图优化/隐藏or显示子图层 前言 实现效果展示 ...

  7. 在小程序中将多个view居中显示

    我们在这里要实现的效果是这样的,在小程序中将多个view居中显示 先看一下效果图 如下图效果所示:我们需要将 "延长收货","查看物流","提醒发货& ...

  8. view中显示部分区域

    在android中有时候要求只显示view的部分区域,这个时候就需要对当前的view进行剪裁的操作.在android中剪裁当前的view的有两种方法:一种是直接截取view,第二种是通过Outline ...

  9. android 在指定位置添加布局,Android 如何动态添加 View 并显示在指定位置。

    引子 最近,在做产品的需求的时候,遇到 PM 要求在某个按钮上添加一个新手引导动画,引导用户去点击.作为 RD,我哗啦啦的就写好相关逻辑了.自测完成后,提测,PM Review 效果. 看完后,PM ...

最新文章

  1. js实现页面跳转的几种方式
  2. Socket编程原理概述
  3. top中的res只增不减_tensorflow中张量排序与accuracy计算
  4. 程序员高效学习的六原则
  5. SpringMVC中请求路径参数使用正则表达式
  6. 网页设计中常用的Web安全字体
  7. 记录各大吃播饭店地址
  8. 如何对计算机进行磁盘整理,如何对Windows 7进行磁盘碎片整理?
  9. 漫谈TCP新算法Elastic-TCP
  10. 搜狗输入法——自定义短语设置
  11. AtCoder Beginner Contest 214(补题)
  12. feign调用简单实例
  13. 离散数学考前复习:(三)计数
  14. 【javaweb简单教程】1.搭建Web环境、初识JSP
  15. 系统自带功能之视频压缩
  16. SVM支持向量机sklearn-wine红酒数据集代码V1
  17. win10 设定计划任务时提示所指定的账户名称无效,如何解决?
  18. 星际争霸1终于可以在win10上运行了
  19. J2SE和J2EE的比较
  20. 《蹭课神器》Alpha版使用说明

热门文章

  1. Variable和Tensor合并后,PyTorch的代码要怎么改?
  2. 面试热点Redis分布式锁,再细说一次
  3. 实现数据“一键脱敏”,Sharding Sphere帮你搞定
  4. 美团二面:Redis与MySQL双写一致性如何保证?
  5. 强烈不建议你用 a.equals(b) 判断对象相等!
  6. 阿里一面:如何保障消息100%投递成功、消息幂等性?
  7. 只知道用它打印了Hello World,除此之外你了解多少呢?
  8. 那些年,我们见过的 Java 服务端乱象
  9. Openresty最佳案例 | 第5篇:http和C_json模块
  10. Python数据处理入门教程!