4.4【HarmonyOS鸿蒙开发】组件ListContainer(下)性能优化

作者:韩茹

公司:程序咖(北京)科技有限公司

鸿蒙巴士专栏作家

在适配ListContainer的数据时,无论是新创建的列表项实例,还是从缓存中获取到的,都须要调用办法findComponentById()获取所有子组件并进行数据填充,大量调用该办法,会损耗ListContainer的性能。比拟好的解决方案是在创立列表项实例时进行调用,将获取到的所有子组件绑定到列表项的实例中,当从缓存中获取到列表项实例后,间接应用绑定的的子组件填充新数据。

咱们从新写一个例子,预期效果图如下:

<img src="https://img.chengxuka.com/listcontaineryunxing9.gif" alt="listcontaineryunxing9" style="zoom:50%;" />

这里阐明一下,文档接上一篇,我的项目我也没有从新创立,还是在上一篇文档中的我的项目根底上来写的。

残缺示例代码如下:

1、首先咱们先在layout下新建一个布局文件。listcontainer_layout2.xml,咱们先搁置一个ListContainer控件:

<?xml version="1.0" encoding="utf-8"?><DirectionalLayout    xmlns:ohos="http://schemas.huawei.com/res/ohos"    ohos:height="match_parent"    ohos:width="match_parent"    ohos:padding="8vp"    ohos:orientation="vertical">        <ListContainer        ohos:id="$+id:list_container3"        ohos:height="match_parent"        ohos:width="match_parent"/></DirectionalLayout>

而后持续创立xml文件,用于示意ListContainer中每个Item的布局款式,list_item_demo3_setting.xml,代码如下:

<?xml version="1.0" encoding="utf-8"?><DirectionalLayout    xmlns:ohos="http://schemas.huawei.com/res/ohos"    ohos:height="80vp"    ohos:width="match_parent"    ohos:padding="8vp"    ohos:orientation="horizontal">    <Image        ohos:id="$+id:ima_setting"        ohos:height="match_parent"        ohos:width="0"        ohos:layout_alignment="vertical_center"        ohos:weight="2">    </Image>    <Text        ohos:id="$+id:text_setting"        ohos:height="match_content"        ohos:width="0"        ohos:padding="4fp"        ohos:text_size="20fp"        ohos:start_padding="8vp"        ohos:end_padding="8vp"        ohos:weight="6"        ohos:layout_alignment="vertical_center"/>    <Switch        ohos:id="$+id:switch_setting"        ohos:height="20vp"        ohos:width="0vp"        ohos:weight="1"        ohos:layout_alignment="vertical_center"/></DirectionalLayout>

2、graphic目录下,咱们创立好资源文件,因为这里用到了switch开关按钮,咱们设计几个款式:

thumb_off_element.xml:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:ohos="http://schemas.huawei.com/res/ohos"       ohos:shape="oval">    <solid        ohos:color="#FFFFFF"/>    <bounds        ohos:top="0"        ohos:left="0"        ohos:right="20vp"        ohos:bottom="20vp"/></shape>

thumb_on_element.xml:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:ohos="http://schemas.huawei.com/res/ohos"       ohos:shape="oval">    <solid        ohos:color="#1E90FF"/>    <bounds        ohos:top="0"        ohos:left="0"        ohos:right="20vp"        ohos:bottom="20vp"/></shape>

track_off_element.xml:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:ohos="http://schemas.huawei.com/res/ohos"       ohos:shape="rectangle">    <solid        ohos:color="#808080"/>    <corners        ohos:radius="20vp"/></shape>

track_on_element.xml:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:ohos="http://schemas.huawei.com/res/ohos"       ohos:shape="rectangle">    <solid        ohos:color="#87CEFA"/>    <corners        ohos:radius="20vp"/></shape>

到此对于页面布局局部,咱们曾经筹备结束。

3、在provider包下,新建一个文件SettingItem.java。该类中的属性,就是对应ListContainer中每个Item条目对应的数据。

package com.example.hanrulistcontainer.provider;public class SettingItem {    private int imageId;    private String settingName;    private boolean isChecked;    public SettingItem(int imageId, String settingName, boolean isChecked) {        this.imageId = imageId;        this.settingName = settingName;        this.isChecked = isChecked;    }    public int getImageId() {        return imageId;    }    public void setImageId(int imageId) {        this.imageId = imageId;    }    public String getSettingName() {        return settingName;    }    public void setSettingName(String settingName) {        this.settingName = settingName;    }    public boolean isChecked() {        return isChecked;    }    public void setChecked(boolean checked) {        isChecked = checked;    }}

4、在该包下持续创立java文件,创立SettingProvider.java

package com.example.hanrulistcontainer.provider;import com.example.hanrulistcontainer.ResourceTable;import ohos.aafwk.ability.AbilitySlice;import ohos.agp.components.*;import ohos.agp.components.element.ShapeElement;import ohos.agp.components.element.StateElement;import java.util.List;public class SettingProvider extends BaseItemProvider {    // ListContainer的数据汇合    private List<SettingItem> settingList;    private AbilitySlice slice;    public SettingProvider(List<SettingItem> list, AbilitySlice slice) {        this.settingList = list;        this.slice = slice;    }    @Override    public int getCount() {        return settingList == null ? 0 : settingList.size();    }    @Override    public Object getItem(int position) {        if (settingList != null && position >= 0 && position < settingList.size()){            return settingList.get(position);        }        return null;    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public Component getComponent(int position, Component component, ComponentContainer componentContainer) {        final Component cpt;        SettingHolder holder;        SettingItem setting = settingList.get(position);        if (component == null) {            cpt = LayoutScatter.getInstance(slice).parse(ResourceTable.Layout_list_item_demo3_setting, null, false);            holder = new SettingHolder(cpt);            // 将获取到的子组件信息绑定到列表项的实例中            cpt.setTag(holder);        } else {            cpt = component;            // 从缓存中获取到列表项实例后,间接应用绑定的子组件信息进行数据填充。            holder = (SettingHolder) cpt.getTag();        }        holder.settingIma.setPixelMap(setting.getImageId());        holder.settingText.setText(setting.getSettingName());        holder.settingSwitch.setChecked(setting.isChecked());        return cpt;    }        // 用于保留列表项中的子组件信息    // 应用该外部类,目标是为了缩小findComponentById被调用的次数,从而优化性能。    public class SettingHolder {        Image settingIma;        Text settingText;        Switch settingSwitch;        SettingHolder(Component component) {            settingIma = (Image) component.findComponentById(ResourceTable.Id_ima_setting);            settingText = (Text) component.findComponentById(ResourceTable.Id_text_setting);            settingSwitch = (Switch) component.findComponentById(ResourceTable.Id_switch_setting);            // 设置switch的开关            settingSwitch.setTrackElement(trackElementInit(                    new ShapeElement(slice, ResourceTable.Graphic_track_on_element),                    new ShapeElement(slice, ResourceTable.Graphic_track_off_element)));            settingSwitch.setThumbElement(thumbElementInit(                    new ShapeElement(slice, ResourceTable.Graphic_thumb_on_element),                    new ShapeElement(slice, ResourceTable.Graphic_thumb_off_element)));        }        private StateElement trackElementInit(ShapeElement on, ShapeElement off) {            StateElement trackElement = new StateElement();            trackElement.addState(new int[]{ComponentState.COMPONENT_STATE_CHECKED}, on);            trackElement.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, off);            return trackElement;        }        private StateElement thumbElementInit(ShapeElement on, ShapeElement off) {            StateElement thumbElement = new StateElement();            thumbElement.addState(new int[]{ComponentState.COMPONENT_STATE_CHECKED}, on);            thumbElement.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, off);            return thumbElement;        }    }}

阐明:这里应用了SettingHolder这个外部类,目标是为了缩小findComponentById被调用的次数。

5、在slice目录下创立一个新的AbilitySlice文件:ThirdAbilitySlice.java

package com.example.hanrulistcontainer.slice;import com.example.hanrulistcontainer.ResourceTable;import com.example.hanrulistcontainer.provider.SettingItem;import com.example.hanrulistcontainer.provider.SettingProvider;import ohos.aafwk.ability.AbilitySlice;import ohos.aafwk.content.Intent;import ohos.agp.components.ListContainer;import java.util.ArrayList;import java.util.List;public class ThirdAbilitySlice extends AbilitySlice {    @Override    protected void onStart(Intent intent) {        super.onStart(intent);        setUIContent(ResourceTable.Layout_listcontainer_layout2);        ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_list_container3);        SettingProvider provider = new SettingProvider(getData(), this);        listContainer.setItemProvider(provider);    }    private List<SettingItem> getData() {        ArrayList<SettingItem> data = new ArrayList<>();        for (int i = 0; i < 100; i++) {            data.add(new SettingItem(                    ResourceTable.Media_icon,                    "SettingName" + i,                    i % 3 == 0            ));        }        return data;    }}

6、批改一下程序的 入口:

package com.example.hanrulistcontainer;import com.example.hanrulistcontainer.slice.MainAbilitySlice;import com.example.hanrulistcontainer.slice.SecondAbilitySlice;import com.example.hanrulistcontainer.slice.ThirdAbilitySlice;import ohos.aafwk.ability.Ability;import ohos.aafwk.content.Intent;public class MainAbility extends Ability {    @Override    public void onStart(Intent intent) {        super.onStart(intent);//        super.setMainRoute(MainAbilitySlice.class.getName());//        super.setMainRoute(SecondAbilitySlice.class.getName());        super.setMainRoute(ThirdAbilitySlice.class.getName());    }}

到此代码局部完结,运行程序即可。

目前为止,咱们写的数据都是假数据,等到咱们学习了网络,就能够从网络上获取数据,而后解析,通过ListContainer展现进去了。

更多内容:

1、社区:鸿蒙巴士https://www.harmonybus.net/

2、公众号:HarmonyBus

3、技术交换QQ群:714518656

4、视频课:https://www.chengxuka.com