程序员

2020征文-手机图解鸿蒙列表组件ListContainer

作者:admin 2021-06-17 我要评论

想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区 https://harmonyos.51cto.com/#zz 一、什么是ListContainer ListContainer是用来呈现连续...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

想了解更多内容,请访问:

51CTO和华为官方战略合作共建的鸿蒙技术社区

https://harmonyos.51cto.com/#zz

一、什么是ListContainer

ListContainer是用来呈现连续、多行数据的列表组件,包含一系列相同类型的列表项。如下图所示:


二、ListContainer的架构视图

ListContainer的架构视图如下所示:

ListContainer作为列表,其中的列表项数据是由适配器Adapter提供的,适配器Adapter作为ListContainer和数据源之间的中介&桥梁,将数据源中的数据映射到要展示的ListContainer中,ListContainer负责以列表的形式显示适配器Adapter提供的数据。

三、ListContainer的使用步骤

ListContainer的使用步骤主要包括:

1、创建ListContainer

2、创建列表项的布局

3、使用POJO类封装数据源中与每个列表项对应的数据

4、构造数据源

5、构造适配器Adapter

6、将数据源关联到适配器Adapter

7、将适配器Adapter应用到ListContainer

四、ListContainer的使用示例

示例的运行效果如下图所示:

开发步骤如下:

1、创建ListContainer(ability_main.xml)

  1. xmlns:ohos="http://schemas.huawei.com/res/ohos" 
  2.  
  3. ohos:id="$+id:list_container" 
  4.  
  5. ohos:height="match_parent" 
  6.  
  7. ohos:width="match_parent"/> 

2、创建列表项的布局(item.xml)

  1. xmlns:ohos="http://schemas.huawei.com/res/ohos" 
  2.  
  3. ohos:height="match_content" 
  4.  
  5. ohos:width="match_parent" 
  6.  
  7. ohos:orientation="vertical"
  8.  
  9.  
  10. ohos:id="$+id:name" 
  11.  
  12. ohos:height="50vp" 
  13.  
  14. ohos:width="match_parent" 
  15.  
  16. ohos:padding="5vp" 
  17.  
  18. ohos:auto_font_size="true" 
  19.  
  20. ohos:text_alignment="center"/> 
  21.  
  22.  
  23. ohos:height="1vp" 
  24.  
  25. ohos:width="match_parent" 
  26.  
  27. ohos:background_element="#CCCCCC"/> 

3、使用POJO类封装数据源中与每个列表项对应的数据(Item.java)

POJO类指的是:只包含属性和相应的getter和setter,而没有业务逻辑的类。

  1. public class Item { 
  2.  
  3. private String name
  4.  
  5. public Item(String name) { 
  6.  
  7. this.name = name
  8.  
  9.  
  10. public String getName() { 
  11.  
  12. return name
  13.  
  14.  
  15. public void setName(String name) { 
  16.  
  17. this.name = name
  18.  
  19.  

4、构造数据源(MainAbilitySlice.java)

  1. public class MainAbilitySlice extends AbilitySlice { 
  2.  
  3. @Override 
  4.  
  5. public void onStart(Intent intent) { 
  6.  
  7. super.onStart(intent); 
  8.  
  9. super.setUIContent(ResourceTable.Layout_ability_main); 
  10.  
  11. List list = getData(); 
  12.  
  13.  
  14. private List getData() { 
  15.  
  16. List list = new ArrayList<>(); 
  17.  
  18. for (int i = 1; i <= 100; i++) { 
  19.  
  20. list.add(new Item("Item " + i)); 
  21.  
  22.  
  23. return list; 
  24.  
  25.  

5、构造适配器Adapter(MyItemProvider.java)

常用的适配器类是RecycleItemProvider,继承该类时需要重写四个方法:getCount()、getItem()、getItemId()和getComponent()。其中,对于方法getComponent(),当某个列表项从不可见变为可见时会自动调用该方法,在该方法中适配器Adapter会从数据源取数据,并将返回的数据封装在一个Component对象中,以便将该对象返回给ListContainer,从而将数据映射到对应的列表项。

  1. public class MyItemProvider extends RecycleItemProvider { 
  2.  
  3. private List list; 
  4.  
  5. private AbilitySlice slice; 
  6.  
  7. public MyItemProvider(List list, AbilitySlice slice) { 
  8.  
  9. this.list = list; 
  10.  
  11. this.slice = slice; 
  12.  
  13.  
  14. @Override 
  15.  
  16. public int getCount() { 
  17.  
  18. return list.size(); 
  19.  
  20.  
  21. @Override 
  22.  
  23. public Object getItem(int position) { 
  24.  
  25. return list.get(position); 
  26.  
  27.  
  28. @Override 
  29.  
  30. public long getItemId(int position) { 
  31.  
  32. return position; 
  33.  
  34.  
  35. @Override 
  36.  
  37. public Component getComponent(int position, Component convertComponent, ComponentContainer componentContainer) { 
  38.  
  39. convertComponent = LayoutScatter.getInstance(slice) 
  40.  
  41. .parse(ResourceTable.Layout_item, nullfalse); 
  42.  
  43. Text text = (Text) convertComponent.findComponentById(ResourceTable.Id_name); 
  44.  
  45. text.setText(list.get(position).getName()); 
  46.  
  47. return convertComponent; 
  48.  
  49.  

6、将数据源关联到适配器Adapter(MainAbilitySlice.java)

  1. public class MainAbilitySlice extends AbilitySlice { 
  2.  
  3. @Override 
  4.  
  5. public void onStart(Intent intent) { 
  6.  
  7. ...... 
  8.  
  9. List list = getData(); 
  10.  
  11. MyItemProvider myItemProvider = new MyItemProvider(list, this); 
  12.  
  13.  
  14. ...... 
  15.  

7、将适配器Adapter应用到ListContainer(MainAbilitySlice.java)

  1. public class MainAbilitySlice extends AbilitySlice { 
  2.  
  3. @Override 
  4.  
  5. public void onStart(Intent intent) { 
  6.  
  7. ...... 
  8.  
  9. MyItemProvider myItemProvider = new MyItemProvider(list, this); 
  10.  
  11. ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_list_container); 
  12.  
  13. listContainer.setItemProvider(myItemProvider); 
  14.  
  15.  
  16. ...... 
  17.  

五、适配器Adapter的优化

对于上面的第5步,当某个列表项从不可见变为可见时,对于自动调用的方法getComponent(),我们是根据列表项的布局文件item.xml创建了一个列表项的实例。这样的做法性能较差。因为系统会对变为不可见的列表项实例进行缓存,所以对于方法getComponent()中的第二个参数convertComponent有可能不为null。当convertComponent不为null时,说明系统把缓存中的某个列表项实例传递过来了,因此,完全可以复用该列表项实例,而没有必要重新创建一个列表项实例。优化方式如下:

  1. public class MyItemProvider extends RecycleItemProvider { 
  2.  
  3. ...... 
  4.  
  5. @Override 
  6.  
  7. public Component getComponent(int position, Component convertComponent, ComponentContainer componentContainer) { 
  8.  
  9. if (convertComponent == null) { 
  10.  
  11. convertComponent = LayoutScatter.getInstance(slice) 
  12.  
  13. .parse(ResourceTable.Layout_item, nullfalse); 
  14.  
  15.  
  16. Text text = (Text) convertComponent.findComponentById(ResourceTable.Id_name); 
  17.  
  18. text.setText(list.get(position).getName()); 
  19.  
  20. return convertComponent; 
  21.  
  22.  

六、使用ViewHolder对适配器Adapter做终极优化

在上面的代码中,得到列表项实例后(不管是新创建的列表项实例,还是从缓存中获得的列表项实例),都要调用方法findComponentById()以获得列表项中的子组件。调用方法findComponentById()是比较耗费性能的,所以好的做法是:在新创建列表项实例时,就调用方法findComponentById()以获得列表项中的所有子组件,并且将所有子组件通过ViewHolder绑定到列表项实例。这样,当从缓存中获得列表项实例后,就无需再调用方法findComponentById()了,直接获得列表项实例绑定的ViewHolder就可以得到所有子组件了。优化方式如下:

  1. public class MyItemProvider extends RecycleItemProvider { 
  2.  
  3. ...... 
  4.  
  5. @Override 
  6.  
  7. public Component getComponent(int position, Component convertComponent, ComponentContainer componentContainer) { 
  8.  
  9. ViewHolder viewHolder; 
  10.  
  11. if (convertComponent == null) { 
  12.  
  13. convertComponent = LayoutScatter.getInstance(slice) 
  14.  
  15. .parse(ResourceTable.Layout_item, nullfalse); 
  16.  
  17. viewHolder = new ViewHolder(); 
  18.  
  19. viewHolder.text = (Text) convertComponent.findComponentById(ResourceTable.Id_name); 
  20.  
  21. convertComponent.setTag(viewHolder); 
  22.  
  23. else { 
  24.  
  25. viewHolder = (ViewHolder) convertComponent.getTag(); 
  26.  
  27.  
  28. viewHolder.text.setText(list.get(position).getName()); 
  29.  
  30. return convertComponent; 
  31.  
  32.  
  33. class ViewHolder { 
  34.  
  35. Text text; 
  36.  
  37.  

如果你理解了为什么要这么优化,相信你会发现:当列表项中只有一个子组件时,也可以不引入ViewHolder,而是将这个子组件直接绑定到列表项实例。代码如下所示:

  1. public class MyItemProvider extends RecycleItemProvider { 
  2.  
  3. ...... 
  4.  
  5. @Override 
  6.  
  7. public Component getComponent(int position, Component convertComponent, ComponentContainer componentContainer) { 
  8.  
  9. Text text; 
  10.  
  11. if (convertComponent == null) { 
  12.  
  13. convertComponent = LayoutScatter.getInstance(slice) 
  14.  
  15. .parse(ResourceTable.Layout_item, nullfalse); 
  16.  
  17. text = (Text) convertComponent.findComponentById(ResourceTable.Id_name); 
  18.  
  19. convertComponent.setTag(text); 
  20.  
  21. else { 
  22.  
  23. text = (Text) convertComponent.getTag(); 
  24.  
  25.  
  26. text.setText(list.get(position).getName()); 
  27.  
  28. return convertComponent; 
  29.  
  30.  

示例源代码,请见附件。

欢迎订阅我的专栏【图解鸿蒙】:

https://harmonyos.51cto.com/column/27

©著作权归作者和HarmonyOS技术社区共同所有,如需转载,请注明出处,否则将追究法律责任

想了解更多内容,请访问:

51CTO和华为官方战略合作共建的鸿蒙技术社区

https://harmonyos.51cto.com/#zz


本文转载自网络,原文链接:https://harmonyos.51cto.com/#zz

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 阿里巴巴DevOps实践指南(八)| 以特性

    阿里巴巴DevOps实践指南(八)| 以特性

  • 阿里巴巴DevOps实践指南(五)| 业务驱

    阿里巴巴DevOps实践指南(五)| 业务驱

  • RISC-V工具链简介

    RISC-V工具链简介

  • 变局时代:RISC-V处理器架构的技术演变

    变局时代:RISC-V处理器架构的技术演变

腾讯云代理商
海外云服务器