HarmonyOS PageSlider组件使用(二)Provider介绍
想了解更多内容,使r介请访问:
和华为官方合作共建的使r介鸿蒙技术社区
https://harmonyos.51cto.com
一、简要概述
PageSliderProvider是使r介为PageSlider组件提供用于管理页面视图的页面适配器。
PageSliderProvider类提供页面项管理功能,使r介例如计算可用视图的使r介数量和在指定位置创建组件。您需要继承并实现PageSliderProvider,使r介以便在不同的使r介页面上显示多个视图。
PageSliderProvider类的使r介使用比较简单,但在复杂业务场景下使用时,使r介需要做的使r介工作比较多,而且这些工作都有重复性。使r介所以在编写本章节案例的使r介同时,我对PageSliderProvider进行了一下通用封装,使r介并且把代码共享到了码云Gitee上,使r介同时将封装的使r介代码打包成har包,提交到了Maven中央仓库,供大家使用。
码云Gitee仓库地址
二、方法介绍
需要掌握的PageSliderProvider类方法不多,一般只需要重写下面四个方法即可为PageSlider提供Page数据支持。
PageSliderProvider类还提供了Page页面数据刷新需要用到的方法,这部分方法可以相互配合,达到精准更新Page页面数据。站群服务器
三、封装解析
PageSliderProvider是一个abstract抽象类,每次使用此类的时候都需要继承它,并重写相应的抽象方法。这种重复的工作,写多了,既繁琐,又浪费时间,降低开发效率。所以秉着高效易用的目的,先对PageSliderProvider进行一定封装。
数据源的封装。在常规业务开发模式中,为PageSliderProvider提供页面元数据是最基础的工作,一般都是将一个复杂的Object对象实例集合加入到一个List列表中。考虑数据的通用性,这里我们也将采用泛型来封装PageSliderProvider类。
public abstract class BasePageSliderProvider<M> extends PageSliderProvider { //页面加载数据源 private final List<M> mPageSliderSourceData; //构造函数初始化列表集合 public BasePageSliderProvider() { this.mPageSliderSourceData = new ArrayList<>(); } /** * 对外提供清除数据源的操作方法, * * 后续需要根据业务自行判断是否需要调用notifyDataChanged()方法 */ public final void clearSourceData() { mPageSliderSourceData.clear(); } /** * 对外提供设置/重置数据源的操作方法,源码下载 * * 后续需要根据业务自行判断是否需要调用notifyDataChanged()方法 * @param data */ public final void setSourceData(List<M> data) { if (!data.isEmpty()) { mPageSliderSourceData.clear(); mPageSliderSourceData.addAll(data); } } /** * 对外追加数据源的操作方法,可能在加载更多数据的时候有用。 * * 后续需要根据业务自行判断是否需要调用notifyDataChanged()方法 * @param data */ public final void appendSourceData(List<M> data) { if (!data.isEmpty()) { mPageSliderSourceData.addAll(data); } } /** * 对外提供删除指定数据源的操作方法, * * 后续需要根据业务自行判断是否需要调用notifyDataChanged()方法 * @param data */ public final void removeSourceData(M data) { if (data != null) { mPageSliderSourceData.remove(data); } } /** * 对外提供获取指定位置数据的操作方法 * @param position * @return */ public final M getItem(int position) { return mPageSliderSourceData.get(position); } /** * 并使用final修饰,防止子类继承重写,导致出现问题。 * @return */ @Override public final int getCount() { return mPageSliderSourceData.size(); } }在重写PageSliderProvider类的getCount()抽象方法时,对此方法使用了final关键字修饰,目的是为了防止子类继承重写,导致出现问题。
页面视图组件的封装。页面视图组件是嵌入式设备应用开发中最需要关心的一件事情,嵌入式设备因内存资源是有限的的,而页面视图组件占用内存资源都还比较大,处理不好,甚至影响应用的流畅性和稳定性。源码库所以在对页面视图组件封装时,需要考虑视图组件的快速创建和及时回收,防止内存泄露/溢出等问题。
在以往的应用开发经验中,ViewHolder绑定视图组件是一种非常高效解决视图组件回收复再利用的好模式。本次我们也使用这种ViewHolder模式来封装页面视图组件,并在PageSliderProvider类中进行简单的组件回收和再利用处理。
创建一个PageViewHolder类,用于绑定页面视图组件。在PageViewHolder类中进行简单的视图组件封装,业务开发中继承本类,去实现更多跟复杂的组件操作。
public abstract class PageViewHolder { protected final Component component; public PageViewHolder(Component component) { this.component = component; } /** * 返回绑定的视图组件 * @return */ public final Component getComponent() { return component; } }具体的业务开发中,使用的ViewHolder肯定是PageViewHolder的子类,是无法确定具体的实例对象类型的。所以在重写PageSliderProvider类的时候,我们也需要采用泛型来达到通用性。
页面视图组件的回收和再利用,常规简单操作我们都是使用列表或者队列进行存储,模拟回收站功能。在创建组件和销毁组件的方法中进行再利用和回收操作,已达到可以反复循环利用的目的,减少页面视图组件的多次创建带来的性能消耗。
public abstract class BasePageSliderProvider<M, VH extends PageViewHolder> extends PageSliderProvider { //页面PageViewHolder缓存,主要保存当前处于活跃状态的PageViewHolder对象 private final HashMap<Integer, VH> mPageSliderComponentCache; //页面PageViewHolder回收站 private final Queue<VH> mPageSliderComponentRecyclers; public BasePageSliderProvider() { this.mPageSliderComponentCache = new HashMap<>(); this.mPageSliderComponentRecyclers = new LinkedBlockingQueue<>(); } /** * 对外提供获取指定位置PageViewHoder对象的方法 * @param position * @return */ public final VH getPageViewHolder(int position) { return mPageSliderComponentCache.get(position); } @Override public Object createPageInContainer(ComponentContainer componentContainer, int index) { if (componentContainer == null || index >= getCount()) { return Optional.empty(); } //从PageViewHolder回收站中获取对象,如果没有,创建新的PageViewHolder实例 VH pageViewHolder = mPageSliderComponentRecyclers.poll(); if (pageViewHolder == null) { pageViewHolder = onCreatePageViewHolder(componentContainer, index); } onBindPageViewHolder(pageViewHolder, index); componentContainer.addComponent(pageViewHolder.getComponent()); //添加到缓存中 mPageSliderComponentCache.put(index, pageViewHolder); return pageViewHolder; } @Override public void destroyPageFromContainer(ComponentContainer componentContainer, int index, Object object) { if (componentContainer == null || index >= getCount()) { return; } if (object instanceof PageViewHolder) { componentContainer.removeComponent(((PageViewHolder) object).getComponent()); mPageSliderComponentCache.remove(index); //回收已经被销毁的PageViewHolder mPageSliderComponentRecyclers.offer((VH) object); } } @Override public boolean isPageMatchToObject(Component component, Object object) { if (object instanceof PageViewHolder) { return component == ((PageViewHolder) object).getComponent(); } return component == object; } /** * 创建并返回一个PageViewHolder对象 * @param componentContainer * @param position * @return */ protected abstract VH onCreatePageViewHolder(ComponentContainer componentContainer, int position); /** * 为指定位置的PageViewHolder对象绑定数据 * @param holder * @param position */ protected abstract void onBindPageViewHolder(VH holder, int position); }四、应用实战
经过一系列的简单封装,PageSliderProvider类使用起来就简单了。我们就不需要再去为页面数据和组件的绑定,重复的去造轮子。直接从BasePageSliderProvider类继承,重写onCreatePageViewHolder和onBindPageViewHolder两个方法,直接绑定数据即可完成PageSlider组件的数据和页面组件的提供。
1.在工程layout目录下的创建Page页面布局文件。比如:component_page.xml
<?xml version="1.0" encoding="utf-8"?> <DependentLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:height="match_parent" ohos:width="match_parent"> <Text ohos:id="$+id:text_component" ohos:height="match_parent" ohos:width="match_parent" ohos:text_size="32fp" ohos:text_font="sans-serif-medium" ohos:text_weight="800" ohos:text_color="#ffffff" ohos:text_alignment="center"/> </DependentLayout>2.继承PageViewHolder类,绑定Page页面布局组件。比如:CasePageViewHolder
private static class CasePageViewHolder extends PageViewHolder { private Text mTextCom; public CasePageViewHolder(Component component) { super(component); mTextCom = (Text) component.findComponentById(ResourceTable.Id_text_component); } public void setText(String text) { mTextCom.setText(text); } public void setBackground(RgbColor color) { ShapeElement element = new ShapeElement(); element.setShape(ShapeElement.RECTANGLE); element.setRgbColor(color); mTextCom.setBackground(element); } }3.继承BasePageSliderProvider类,绑定Page页面数据源和PageViewHolder。
private static class CasePageSliderProvider extends BasePageSliderProvider<PageInfo, CasePageViewHolder> { @Override protected CasePageViewHolder onCreatePageViewHolder(ComponentContainer componentContainer, int position) { LayoutScatter layoutScatter = LayoutScatter.getInstance(componentContainer.getContext()); Component component = layoutScatter.parse(ResourceTable.Layout_component_page, componentContainer, false); return new CasePageViewHolder(component); } @Override protected void onBindPageViewHolder(CasePageViewHolder holder, int position) { PageInfo pageInfo = getItem(position); holder.setText(pageInfo.getContent()); holder.setBackground(pageInfo.getColor()); } }4.初始Page页面元数据和PageSlider组件,并将PageSliderProvider对象绑定到PageSlider组件中。
public class MainAbilitySlice extends AbilitySlice { private PageSlider mPageSlider; private CasePageSliderProvider mPageSliderProvider; @Override public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_ability_main); mPageSlider = (PageSlider) findComponentById(ResourceTable.Id_page_slider_component); mPageSliderProvider = new CasePageSliderProvider(); mPageSliderProvider.setSourceData(createAndInitPageData()); mPageSlider.setProvider(mPageSliderProvider); } //初始化Page页面元数据 private List<PageInfo> createAndInitPageData(){ List<PageInfo> initData = new ArrayList<>(); for (int i = 0; i < 15; i++) { PageInfo pageInfo = new PageInfo(); char tempChar = (char) (new Random().nextInt(26) + 65); pageInfo.setContent("Case " + String.valueOf(tempChar)); pageInfo.setColor(new RgbColor( new Random().nextInt(255), new Random().nextInt(255), new Random().nextInt(255))); initData.add(pageInfo); } return initData; } private static class PageInfo { private String content; private RgbColor color; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public RgbColor getColor() { return color; } public void setColor(RgbColor color) { this.color = color; } } }五、总结
这里只是简单的对PageSliderProvider类进行了一下封装试用,并将代码提交到了码云Gitee仓库,并进行了Maven中央仓库管理。PageSliderProvider类其实还可以进行更多功能改造,封装的更加高效易用,如果有意向,可以直接在码云Gitee仓库进行代码共享哦。
想了解更多内容,请访问:
和华为官方合作共建的鸿蒙技术社区
https://harmonyos.51cto.com