HarmonyOS PageSlider組件使用(二)Provider介紹
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
一、簡要概述
PageSliderProvider是為PageSlider組件提供用于管理頁面視圖的頁面適配器。
PageSliderProvider類提供頁面項管理功能,例如計算可用視圖的數(shù)量和在指定位置創(chuàng)建組件。您需要繼承并實現(xiàn)PageSliderProvider,以便在不同的頁面上顯示多個視圖。
PageSliderProvider類的使用比較簡單,但在復(fù)雜業(yè)務(wù)場景下使用時,需要做的工作比較多,而且這些工作都有重復(fù)性。所以在編寫本章節(jié)案例的同時,我對PageSliderProvider進行了一下通用封裝,并且把代碼共享到了碼云Gitee上,同時將封裝的代碼打包成har包,提交到了Maven中央倉庫,供大家使用。
二、方法介紹
需要掌握的PageSliderProvider類方法不多,一般只需要重寫下面四個方法即可為PageSlider提供Page數(shù)據(jù)支持。
PageSliderProvider類還提供了Page頁面數(shù)據(jù)刷新需要用到的方法,這部分方法可以相互配合,達(dá)到精準(zhǔn)更新Page頁面數(shù)據(jù)。
三、封裝解析
PageSliderProvider是一個abstract抽象類,每次使用此類的時候都需要繼承它,并重寫相應(yīng)的抽象方法。這種重復(fù)的工作,寫多了,既繁瑣,又浪費時間,降低開發(fā)效率。所以秉著高效易用的目的,先對PageSliderProvider進行一定封裝。
數(shù)據(jù)源的封裝。在常規(guī)業(yè)務(wù)開發(fā)模式中,為PageSliderProvider提供頁面元數(shù)據(jù)是最基礎(chǔ)的工作,一般都是將一個復(fù)雜的Object對象實例集合加入到一個List列表中??紤]數(shù)據(jù)的通用性,這里我們也將采用泛型來封裝PageSliderProvider類。
- public abstract class BasePageSliderProvider<M> extends PageSliderProvider {
- //頁面加載數(shù)據(jù)源
- private final List<M> mPageSliderSourceData;
- //構(gòu)造函數(shù)初始化列表集合
- public BasePageSliderProvider() {
- this.mPageSliderSourceData = new ArrayList<>();
- }
- /**
- * 對外提供清除數(shù)據(jù)源的操作方法,
- *
- * 后續(xù)需要根據(jù)業(yè)務(wù)自行判斷是否需要調(diào)用notifyDataChanged()方法
- */
- public final void clearSourceData() {
- mPageSliderSourceData.clear();
- }
- /**
- * 對外提供設(shè)置/重置數(shù)據(jù)源的操作方法,
- *
- * 后續(xù)需要根據(jù)業(yè)務(wù)自行判斷是否需要調(diào)用notifyDataChanged()方法
- * @param data
- */
- public final void setSourceData(List<M> data) {
- if (!data.isEmpty()) {
- mPageSliderSourceData.clear();
- mPageSliderSourceData.addAll(data);
- }
- }
- /**
- * 對外追加數(shù)據(jù)源的操作方法,可能在加載更多數(shù)據(jù)的時候有用。
- *
- * 后續(xù)需要根據(jù)業(yè)務(wù)自行判斷是否需要調(diào)用notifyDataChanged()方法
- * @param data
- */
- public final void appendSourceData(List<M> data) {
- if (!data.isEmpty()) {
- mPageSliderSourceData.addAll(data);
- }
- }
- /**
- * 對外提供刪除指定數(shù)據(jù)源的操作方法,
- *
- * 后續(xù)需要根據(jù)業(yè)務(wù)自行判斷是否需要調(diào)用notifyDataChanged()方法
- * @param data
- */
- public final void removeSourceData(M data) {
- if (data != null) {
- mPageSliderSourceData.remove(data);
- }
- }
- /**
- * 對外提供獲取指定位置數(shù)據(jù)的操作方法
- * @param position
- * @return
- */
- public final M getItem(int position) {
- return mPageSliderSourceData.get(position);
- }
- /**
- * 并使用final修飾,防止子類繼承重寫,導(dǎo)致出現(xiàn)問題。
- * @return
- */
- @Override
- public final int getCount() {
- return mPageSliderSourceData.size();
- }
- }
在重寫PageSliderProvider類的getCount()抽象方法時,對此方法使用了final關(guān)鍵字修飾,目的是為了防止子類繼承重寫,導(dǎo)致出現(xiàn)問題。
頁面視圖組件的封裝。頁面視圖組件是嵌入式設(shè)備應(yīng)用開發(fā)中最需要關(guān)心的一件事情,嵌入式設(shè)備因內(nèi)存資源是有限的的,而頁面視圖組件占用內(nèi)存資源都還比較大,處理不好,甚至影響應(yīng)用的流暢性和穩(wěn)定性。所以在對頁面視圖組件封裝時,需要考慮視圖組件的快速創(chuàng)建和及時回收,防止內(nèi)存泄露/溢出等問題。
在以往的應(yīng)用開發(fā)經(jīng)驗中,ViewHolder綁定視圖組件是一種非常高效解決視圖組件回收復(fù)再利用的好模式。本次我們也使用這種ViewHolder模式來封裝頁面視圖組件,并在PageSliderProvider類中進行簡單的組件回收和再利用處理。
創(chuàng)建一個PageViewHolder類,用于綁定頁面視圖組件。在PageViewHolder類中進行簡單的視圖組件封裝,業(yè)務(wù)開發(fā)中繼承本類,去實現(xiàn)更多跟復(fù)雜的組件操作。
- public abstract class PageViewHolder {
- protected final Component component;
- public PageViewHolder(Component component) {
- this.component = component;
- }
- /**
- * 返回綁定的視圖組件
- * @return
- */
- public final Component getComponent() {
- return component;
- }
- }
具體的業(yè)務(wù)開發(fā)中,使用的ViewHolder肯定是PageViewHolder的子類,是無法確定具體的實例對象類型的。所以在重寫PageSliderProvider類的時候,我們也需要采用泛型來達(dá)到通用性。
頁面視圖組件的回收和再利用,常規(guī)簡單操作我們都是使用列表或者隊列進行存儲,模擬回收站功能。在創(chuàng)建組件和銷毀組件的方法中進行再利用和回收操作,已達(dá)到可以反復(fù)循環(huán)利用的目的,減少頁面視圖組件的多次創(chuàng)建帶來的性能消耗。
- public abstract class BasePageSliderProvider<M, VH extends PageViewHolder> extends PageSliderProvider {
- //頁面PageViewHolder緩存,主要保存當(dāng)前處于活躍狀態(tài)的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回收站中獲取對象,如果沒有,創(chuàng)建新的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);
- //回收已經(jīng)被銷毀的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;
- }
- /**
- * 創(chuàng)建并返回一個PageViewHolder對象
- * @param componentContainer
- * @param position
- * @return
- */
- protected abstract VH onCreatePageViewHolder(ComponentContainer componentContainer, int position);
- /**
- * 為指定位置的PageViewHolder對象綁定數(shù)據(jù)
- * @param holder
- * @param position
- */
- protected abstract void onBindPageViewHolder(VH holder, int position);
- }
四、應(yīng)用實戰(zhàn)
經(jīng)過一系列的簡單封裝,PageSliderProvider類使用起來就簡單了。我們就不需要再去為頁面數(shù)據(jù)和組件的綁定,重復(fù)的去造輪子。直接從BasePageSliderProvider類繼承,重寫onCreatePageViewHolder和onBindPageViewHolder兩個方法,直接綁定數(shù)據(jù)即可完成PageSlider組件的數(shù)據(jù)和頁面組件的提供。
1.在工程layout目錄下的創(chuàng)建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頁面數(shù)據(jù)源和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頁面元數(shù)據(jù)和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頁面元數(shù)據(jù)
- 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;
- }
- }
- }
五、總結(jié)
這里只是簡單的對PageSliderProvider類進行了一下封裝試用,并將代碼提交到了碼云Gitee倉庫,并進行了Maven中央倉庫管理。PageSliderProvider類其實還可以進行更多功能改造,封裝的更加高效易用,如果有意向,可以直接在碼云Gitee倉庫進行代碼共享哦。
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)