美文网首页Android开发经验谈
LayoutManager学习(四)代码重构

LayoutManager学习(四)代码重构

作者: 刘景昌 | 来源:发表于2019-06-19 16:30 被阅读50次

    要实现的效果我们在前三篇的文章中都已经实现了
    但是没有可以一次写出来的完美的代码 我们的代码应该在重构中段前行
    1.合并冗余代码
    再次大家写代码的过程中总是会出现一些重复需要的代码,但是为了时间的缘故我们只是单纯的复制粘贴就好了 也没有去考虑一个良好的代码结构,这些的出现就是我们要处理的冗余代码
    比如我完成这三的的时候冗余的代码就有

     /**
         * 获取RecyclerView的显示高度
         */
        public int getVerticalSpace() {
            return getHeight() - getPaddingTop() - getPaddingBottom();
        }
    
        /**
         * 获取RecyclerView的显示宽度
         */
        public int getHorizontalSpace() {
            return getWidth() - getPaddingLeft() - getPaddingRight();
        }
    
    
        @Override
        public RecyclerView.LayoutParams generateDefaultLayoutParams() {
            return new RecyclerView.LayoutParams(RecyclerView.LayoutParams.WRAP_CONTENT,
                    RecyclerView.LayoutParams.WRAP_CONTENT);
        }
    
    

    至于如何优化一般有两种方式
    1.将重复代码写到工具类中
    2.如果重复代码与本身的基类关联比较密切 我们应该新建一个基类 让他们来继承
    这里我们采用第二种方式
    这只完整的的最基础的基类

    public class BaseLayoutManager extends RecyclerView.LayoutManager {
    
        @Override
        public RecyclerView.LayoutParams generateDefaultLayoutParams() {
            return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        /**
         * 获取RecyclerView的显示高度
         */
        public int getVerticalSpace() {
            return getHeight() - getPaddingTop() - getPaddingBottom();
        }
    
        /**
         * 获取RecyclerView的显示宽度
         */
        public int getHorizontalSpace() {
            return getWidth() - getPaddingLeft() - getPaddingRight();
        }
    
    }
    
    

    2.使用模板
    我们可以使用模板设计模式 来是我们在整个实现过程中保持一个良好的思路
    在做这件事情之前我们先要整理出自己的自定义LayoutManager的实现思路是什么 我们只要按照这个思路实现就行了 后面的人如果去看这个基类也能有一个良好的思路 在这三个实现类中我们要整理的主要部分是 onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state)
    这个方法的实现里面
    所以我们主要就是实现基类中的onLayoutChildren方法
    我们设计的模板

        @Override
        public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
            if (getItemCount() <= 0 || state.isPreLayout()) {
                return;
            }
            //移除所有View
            removeAndRecycleAllViews(recycler);
            initItemView(recycler);
            List<T> itemViewList =  createItemViewInfoList();
    
            detachAndScrapAttachedViews(recycler);
            drawView(recycler, state, itemViewList);
        }
        
        @Override
        public void initItemView(RecyclerView.Recycler recycler) {
    
        }
    
        @Override
        public List<T> createItemViewInfoList() {
            return null;
        }
    
        @Override
        public void drawView(RecyclerView.Recycler recycler, RecyclerView.State state, List<T> itemViewList) {
    
        }
        @Override
        public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
            if (getItemCount() <= 0 || state.isPreLayout()) {
                return;
            }
            //移除所有View
            removeAndRecycleAllViews(recycler);
            initItemView(recycler);
            List<T> itemViewList =  createItemViewInfoList();
            detachAndScrapAttachedViews(recycler);
            drawView(recycler, state, itemViewList);
        }
        
        @Override
        public void initItemView(RecyclerView.Recycler recycler) {
    
        }
    
        @Override
        public List<T> createItemViewInfoList() {
            return null;
        }
    
        @Override
        public void drawView(RecyclerView.Recycler recycler, RecyclerView.State state, List<T> itemViewList) {
    
        }
    
        @Override
        public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
            if (getItemCount() <= 0 || state.isPreLayout()) {
                return;
            }
            //移除所有View
            removeAndRecycleAllViews(recycler);
            initItemView(recycler);
            List<T> itemViewList =  createItemViewInfoList();
          // 在布局之前,将所有的子 View 先 Detach 掉,放入到 Scrap 缓存中
            detachAndScrapAttachedViews(recycler);
            drawView(recycler, state, itemViewList);
        }
        
        @Override
        public void initItemView(RecyclerView.Recycler recycler) {
    
        }
    
        @Override
        public List<T> createItemViewInfoList() {
            return null;
        }
    
        @Override
        public void drawView(RecyclerView.Recycler recycler, RecyclerView.State state, List<T> itemViewList) {
    
        }
    

    设计的接口

    public interface LayoutManagerInterface<T> {
        /***
         * 初始化绘制参数
         * @param recycler
         */
        void initItemView(RecyclerView.Recycler recycler) ;
    
        /***
         * 创建绘制界面所需要的bean
         * @return
         */
        List<T> createItemViewInfoList() ;
    
        /***
         * 实际绘制
         * @param recycler
         * @param state
         * @param itemViewList
         */
         void drawView(RecyclerView.Recycler recycler, RecyclerView.State state, List<T> itemViewList) ;
    }
    
    

    在这做的时候有两个想法
    1.使用泛型是每个实现类都自己的实体类

    1. 写一个包含所有的属性的bean 每个实现类都使用这实体类
      虽然感觉两个都可以,但是最终选择了 1 至于为什么 我也不知道直觉吧
      这样我们最基础的模板就大好了 我们就可以去改在具体的实现类了 后面我们发现有什么共有的特征可以在玩基类里面加
      我在这里只是说以下一个的改造 感觉写的时候第一个最差也最容易就改第一个吧。
      首先我们应该有一个控制类来控制list的信息的配置和list的创建并和View的绘制个里所以有了TanTanControl类
    public class TanTanControl {
    
        private int count = 4;
        private float scale = 0.05f;
        private int translateY = 100;
    
        public TanTanControl(int count, float scale, int translateY) {
            this.count = count;
            this.scale = scale;
            this.translateY = translateY;
        }
    
        public int getCount() {
            return count;
        }
    
        public float getScale() {
            return scale;
        }
    
        public int getTranslateY() {
            return translateY;
        }
    
        public List<TanTanBean> createItemViewInfoList(int itemCount) {
            int lastPosition;
            if (itemCount < count) {
                lastPosition = 0;
            } else {
                lastPosition = itemCount - count;
            }
            List<TanTanBean> tanTanBeanList = new ArrayList<>();
            for (int position = lastPosition; position < itemCount; position++) {
                TanTanBean tanTanBean = new TanTanBean();
                int level = itemCount - position - 1;
                tanTanBean.setLevel(level);
                //设置每层的Scale和translationY
                if (level > 0) {
                    //设置每一层X方向的缩小
                    tanTanBean.setScaleX(1 - scale * level);
                    if (level < count - 1) {
                        //Y需要缩小的和位移
                        tanTanBean.setTranslateY(translateY * level);
                        tanTanBean.setScaleY(1 - scale * level);
                    } else {
                        //不需要缩小和位移只需要和前一层保持一致
                        tanTanBean.setTranslateY(translateY * (level - 1));
                        tanTanBean.setScaleY(1 - scale * (level - 1));
                    }
                }
                tanTanBeanList.add(tanTanBean);
            }
    
            return tanTanBeanList;
        }
    
    }
    

    在这里面负责逻辑和默认参数的配置
    而新的Layoutmanager只负责View层的绘制

    public class TanTanLayoutManager extends BaseLayoutManager<TanTanBean> {
        TanTanControl tanTanControl;
    
        public TanTanLayoutManager(TanTanControl tanTanControl) {
            this.tanTanControl = tanTanControl;
        }
    
        @Override
        public void initItemView(RecyclerView.Recycler recycler) {
    
        }
    
        @Override
        public List<TanTanBean> createItemViewInfoList() {
            return tanTanControl.createItemViewInfoList(getItemCount());
        }
    
        @Override
        public void drawView(RecyclerView.Recycler recycler, RecyclerView.State state, List<TanTanBean> itemViewList) {
            int itemCount = getItemCount();
            if (itemCount < 1) {
                return;
            }
            for (int i = 0; i < itemViewList.size(); i++) {
                TanTanBean tanTanBean = itemViewList.get(i);
                View view = recycler.getViewForPosition(itemCount - tanTanBean.getLevel() - 1);
                addView(view);
                measureChildWithMargins(view, 0, 0);
                int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
                int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
                layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 4,
                        widthSpace / 2 + getDecoratedMeasuredWidth(view),
                        heightSpace / 4 + getDecoratedMeasuredHeight(view));
                if (tanTanBean.getLevel() > 0) {
                    view.setScaleX(tanTanBean.getScaleX());
                    view.setTranslationY(tanTanBean.getTranslateY());
                    view.setScaleY(tanTanBean.getScaleY());
                }
            }
        }
    }
    

    他们两件中间联系的纽带实体类

    public class TanTanBean {
        private int translateY;
        private  float scaleX;
        private  float scaleY;
        private int level;
    }
    

    这样改造基本就完成了 然后就是抽时间吧另外两个也改了

    修改后demo :https://github.com/525642022/LayoutManagerTest

    相关文章

      网友评论

        本文标题:LayoutManager学习(四)代码重构

        本文链接:https://www.haomeiwen.com/subject/odfhqctx.html