tool

Fraction的封装

2021-01-03  本文已影响0人  裴云飞

一、前言

上篇文章介绍了Fraction,如果你还不知道如何使用Fraction,可以阅读Fraction的使用和生命周期这篇文章。

((FractionAbility) getAbility()).getFractionManager()
                .startFractionScheduler()
                .add(ResourceTable.Id_stack, new HomeFraction(), "home_fraction")
                .submit();

在上篇文章中主要是使用上面的代码来将Fraction添加带AbilitySlice里面。请注意,之前只用到了一个Fraction,在实际开发中,肯定会有很多Fraction,那么有多少个Fraction,上面的代码就需要写多少次,这些都是重复的代码,遇到重复代码,就需要对其进行封装,封装后,上面的那段代码就不需要外界来写了。

二、效果图

三、封装

/**
 * fraction父类
 *
 * @author 裴云飞
 * @date 2020/12/30
 */
public abstract class BaseFraction extends Fraction {

    protected Component mComponent;

    /**
     * 获取布局文件的id
     *
     * @return 布局文件的id
     */
    public abstract int getUIContent();

    /**
     * 初始化组件
     */
    public abstract void initComponent();

    @Override
    protected Component onComponentAttached(LayoutScatter scatter, ComponentContainer container, Intent intent) {
        // 将布局文件转换成组件对象
        mComponent = scatter.parse(getUIContent(), container, false);
        // 初始化组件
        initComponent();
        return mComponent;
    }

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
    }

    @Override
    protected void onActive() {
        super.onActive();
    }

    @Override
    protected void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    protected void onInactive() {
        super.onInactive();

    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    /**
     * 获取string.json文件中定义的字符串
     *
     * @param resId
     * @return
     */
    public String getString(int resId) {
        try {
            return getFractionAbility().getResourceManager().getElement(resId).getString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取color.json文件中定义颜色值
     *
     * @param colorId
     * @return
     */
    public int getColor(int colorId) {
        try {
            return getFractionAbility().getResourceManager().getElement(colorId).getColor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
}
public class CategoryFraction extends BaseFraction {

    @Override
    public int getUIContent() {
        return ResourceTable.Layout_fraction_category;
    }

    @Override
    public void initComponent() {

    }
}

四、Fraction配合底部导航栏

1、在鸿蒙系统—打造通用的底部导航栏这篇文章中,我们封装了一个通用的底部导航栏,当时并没有使用Fraction,这次就使用Fraction。之前的底部导航栏总共有5个条目,每个条目都需要创建一个Fraction,并且继承BaseFraction,当点击某个条目,需要先将之前显示的Fraction隐藏掉,然后显示新的Fraction。比如,当前显示的是首页的Fraction,当点击收藏后,就需要先隐藏首页的Fraction,然后显示收藏的Fraction。
2、创建BarComponentProvider,这个是适配器类,也是个抽象类,子类需要重写getPage和getCount方法,getPage方法用于创建Fraction对象,getCount方法用于返回fraction的总数。
3、在构造方法里面让外界将FractionManager对象传递过来。
4、在createPageInContainer里面调用mFractionManager.startFractionScheduler开启事务,如果当前的fraction不为空,就隐藏当前的fraction,然后根据标签从FractionManager里面获取fraction,如果获取的fraction不为空,那就显示出来。如果获取的fraction为空,调用getPage方法创建fraction,将创建好的fraction添加到fractionScheduler,最后提交事务。
5、PlainArray是鸿蒙提供的一个集合,用于存储以整型作为键、以任何对象作为值的数据结构,PlainArray节省了内存,使用二分搜索查找元素。getPage方法用于创建对象,由于子类是通过反射创建fraction对象的,反射创建对象要比直接new一个对象更耗性能,所以使用缓存。首先从缓存里面查找,如果能查找到直接返回,否则让子类来创建对象,并将创建好的对象存入缓存。

public abstract class BarComponentProvider {

    /**
     * 当前的fraction
     */
    protected Fraction mCurFraction;
    /**
     * fraction管理器
     */
    protected FractionManager mFractionManager;

    private PlainArray<Fraction> mFractionPlainArray;

    public BarComponentProvider(FractionManager fractionManager) {
        mFractionManager = fractionManager;
        mFractionPlainArray = new PlainArray<>();
    }

    /**
     * 创建fraction,并对fraction进行管理
     *
     * @param container
     * @param position
     */
    public void createPageInContainer(ComponentContainer container, int position) {
        // 开启事务
        FractionScheduler fractionScheduler = mFractionManager.startFractionScheduler();
        if (mCurFraction != null) {
            // 当前的fraction不为空,就隐藏
            fractionScheduler.hide(mCurFraction);
        }
        String tag = container.getId() + ":" + position;
        Fraction fraction;
        // 根据标签从FractionManager里面获取fraction
        Optional<Fraction> fractionOptional = mFractionManager.getFractionByTag(tag);
        if (fractionOptional.isPresent()) {
            fraction = fractionOptional.get();
            // 获取的fraction不为空,显示出来
            fractionScheduler.show(fraction);
        } else {
            // 获取的fraction为空,创建fraction
            fraction = getPage(position);
            // 将fraction添加到fractionScheduler
            fractionScheduler.add(container.getId(), fraction, tag);
        }
        mCurFraction = fraction;
        // 提交事务
        fractionScheduler.submit();
    }

    /**
     * 根据位置创建fraction对象
     *
     * @param position 位置
     * @return fraction对象
     */
    public Fraction getPage(int position) {
        // 从缓存获取fraction对象
        Optional<Fraction> fractionOptional = mFractionPlainArray.get(position);
        if (fractionOptional.isPresent()) {
            // 存在,直接返回
            return fractionOptional.get();
        }
        // 不存在fraction对象,则让子类通过反射创建fraction对象
        Fraction fraction = getFraction(position);
        // 将创建好点的对象添加到缓存
        mFractionPlainArray.put(position, fraction);
        return fraction;
    }

    public abstract Fraction getFraction(int position);

    /**
     * fragment的总数
     *
     * @return fragment的总数
     */
    public abstract int getCount();

    /**
     * 获取当前的fraction
     *
     * @return 当前的fraction
     */
    public Fraction getCurrentFraction() {
        return mCurFraction;
    }
}

5、子类继承BarComponentProvider,集合里面就是底部导航栏中每个条目的数据,

public class BottomBarComponentProvider extends BarComponentProvider {

    private List<BottomBarInfo<?>> mInfoList;

    public BottomBarComponentProvider(List<BottomBarInfo<?>> infoList, FractionManager fractionManager) {
        super(fractionManager);
        mInfoList = infoList;
    }

    @Override
    public Fraction getPage(int position) {
        try {
            return mInfoList.get(position).fraction.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public int getCount() {
        return mInfoList.size();
    }

}

6、在Fraction的使用和生命周期这篇文章中,我们是在布局文件中添加了一个栈布局。这次创建FractionBarComponent类,继承栈布局。setProvider方法用于设置适配器,这个适配器就是上面创建BarComponentProvider。setCurrentItem用于设置点前要显示的fraction,如果没有设置适配器,什么都不干。如果传递过来的位置与当前位置不相等,那就创建fraction。点击底部导航栏的时候,就会调用setCurrentItem方法

public class FractionBarComponent extends StackLayout {

    private BarComponentProvider mProvider;
    private int currentPosition;

    public FractionBarComponent(Context context) {
        this(context, null);
    }

    public FractionBarComponent(Context context, AttrSet attrSet) {
        this(context, attrSet, "");
    }

    public FractionBarComponent(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
    }

    /**
     * 设置适配器
     *
     * @param provider
     */
    public void setProvider(BarComponentProvider provider) {
        if (mProvider != null || provider == null) {
            return;
        }
        currentPosition = -1;
        mProvider = provider;
    }

    /**
     * 设置点前要显示的fraction
     *
     * @param position
     */
    public void setCurrentItem(int position) {
        if (position < 0 || position >= mProvider.getCount()) {
            return;
        }
        if (currentPosition != position) {
            currentPosition = position;
            mProvider.createPageInContainer(this, position);
        }
    }

    public int getCurrentItem() {
        return currentPosition;
    }

    public Fraction getCurrentFraction() {
        if (mProvider == null) {
            return null;
        }
        return mProvider.getCurrentFraction();
    }
}

8、在布局文件中使用,外层就是底部导航栏,底部导航栏里面就是一个栈布局

<?xml version="1.0" encoding="utf-8"?>
<com.pyf.ui.bar.bottom.BottomNavigationBar
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:id="$+id:bottom_navigation_bar"
    ohos:orientation="vertical"
    ohos:width="match_parent">

    <com.pyf.common.bar.FractionBarComponent
        ohos:height="match_parent"
        ohos:id="$+id:fraction_bar_component"
        ohos:width="match_parent"/>

</com.pyf.ui.bar.bottom.BottomNavigationBar>

9、在代码使用,最关键的代码就是当点击底部导航栏的时候,调用setCurrentItem方法显示fraction,该方法内部会先隐藏之前的fraction,然后显示新的fraction。

private void initBottom() {
        tabBottomLayout = (BottomNavigationBar) mAbilitySliceProvider.findComponentById(ResourceTable.Id_bottom_navigation_bar);
        bottomInfoList = new ArrayList<>();
        // 获取string.json文件中定义的字符串
        String home = mAbilitySliceProvider.getString(ResourceTable.String_home);
        String favorite = mAbilitySliceProvider.getString(ResourceTable.String_favorite);
        String category = mAbilitySliceProvider.getString(ResourceTable.String_category);
        String find = mAbilitySliceProvider.getString(ResourceTable.String_find);
        String profile = mAbilitySliceProvider.getString(ResourceTable.String_profile);
        // 首页
        BottomBarInfo<Integer> homeInfo = new BottomBarInfo<>(home,
                ResourceTable.Media_home_normal,
                ResourceTable.Media_home_selected,
                defaultColor, tintColor);
        homeInfo.fraction = HomeFraction.class;
        // 收藏
        BottomBarInfo<Integer> favoriteInfo = new BottomBarInfo<>(favorite,
                ResourceTable.Media_favorite_normal,
                ResourceTable.Media_favorite_selected,
                defaultColor, tintColor);
        favoriteInfo.fraction = FavoriteFraction.class;
        // 分类
        BottomBarInfo<Integer> categoryInfo = new BottomBarInfo<>(category,
                ResourceTable.Media_category_normal,
                ResourceTable.Media_category_selected,
                defaultColor, tintColor);
        categoryInfo.fraction = CategoryFraction.class;
        // 发现
        BottomBarInfo<Integer> findInfo = new BottomBarInfo<>(find,
                ResourceTable.Media_recommend_normal,
                ResourceTable.Media_recommend_selected,
                defaultColor, tintColor);
        findInfo.fraction = FindFraction.class;
        // 我的
        BottomBarInfo<Integer> profileInfo = new BottomBarInfo<>(profile,
                ResourceTable.Media_profile_normal,
                ResourceTable.Media_profile_selected,
                defaultColor, tintColor);
        profileInfo.fraction = ProfileFraction.class;

        // 将每个条目的数据放入到集合
        bottomInfoList.add(homeInfo);
        bottomInfoList.add(favoriteInfo);
        bottomInfoList.add(categoryInfo);
        bottomInfoList.add(findInfo);
        bottomInfoList.add(profileInfo);
        // 设置底部导航栏的透明度
        tabBottomLayout.setBarBottomAlpha(0.85f);
        // 初始化所有的条目
        tabBottomLayout.initInfo(bottomInfoList);
        initFractionBarComponent();
        tabBottomLayout.addBarSelectedChangeListener((index, prevInfo, nextInfo) ->
                        // 显示fraction
                        mFractionBarComponent.setCurrentItem(index));
        // 设置默认选中的条目,该方法一定要在最后调用
        tabBottomLayout.defaultSelected(homeInfo);
    }

    private void initFractionBarComponent() {
        FractionManager fractionManage = mAbilitySliceProvider.getFractionManager();
        BottomBarComponentProvider provider = new BottomBarComponentProvider(bottomInfoList, fractionManage);
        mFractionBarComponent = (FractionBarComponent) mAbilitySliceProvider.findComponentById(ResourceTable.Id_fraction_bar_component);
        mFractionBarComponent.setProvider(provider);
    }

最后附上源码

欢迎阅读我的其它文章
鸿蒙系统—实现通用的下拉刷新组件

上一篇下一篇

猜你喜欢

热点阅读