RecyclerView完全解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: RecyclerView已经出现有一段时间了,但网上找了很久,并没有过多的介绍,还是鸿洋大神写的博客比较详细,我这里就按我的思路又加工了下。
RecyclerView已经出现有一段时间了,但网上找了很久,并没有过多的介绍,还是鸿洋大神写的博客比较详细,我这里就按我的思路又加工了下。使用时,必须有support-v7包才可以使用。相比ListView,GridView之类控件,它有很多的优点,例如:数据绑定、Item View创建,View的回收以及重用等机制。RecyclerView控件和ListView的原理有很多相似的地方,都是维护少量的View来进行显示大量的数据,不过RecyclerView控件比ListView更加高级并且更加灵活。当我们的数据发生改变的时候也能很好的进行显示。和ListView不同的是,RecyclerView不用再负责Item的显示相关的功能,其所有有关布局,绘制,数据绑定等都被分拆成不同的类进行管理,比如:
  • 通过布局管理器LayoutManager可以处理Item的布局
  • 通过ItemDecoration,可以控制Item间的间隔(可绘制)
  • 通过ItemAnimator,可以控制Item增删的动画

为了使用RecyclerView控件,我们需要创建一个Adapter和一个LayoutManager

Adapter:继承自RecyclerView.Adapetr类,主要用来将数据和布局item进行绑定。

LayoutManager:布局管理器,设置每一项view在RecyclerView中的位置布局以及控件item view的显示或者隐藏.当View重用或者回收的时候,LayoutManger都会向Adapter请求新的数据来替换原来的数据内容。这种回收重用的机制可以提高性能,避免创建很多的view或者是频繁的调用findViewById方法。这种机制和ListView还是很相似的。

RecyclerView提供了三种内置的LayoutManager:

  1. LinearLayoutManager:线性布局,横向或者纵向滑动列表
  2. GridLayoutManager:表格布局
  3. StaggeredGridLayoutManager:流式布局,例如瀑布流效果

当然除了上面的三种内部布局之外,我们还可以继承RecyclerView.LayoutManager来实现一个自定义的LayoutManager。


Animations(动画)效果:

RecyclerView对于Item的添加和删除是默认开启动画的。我们当然也可以通过RecyclerView.ItemAnimator类定制动画,然后通过RecyclerView.setItemAnimator()方法来进行使用。


activity_main.xml布局如下

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="#ffff0000"
        android:dividerHeight="10dp" />

</RelativeLayout>

MainActivity.java如下:
public class MainActivity extends Activity {
    private RecyclerView mRecyclerView;
     private LinearLayoutManager mLayoutManager;
     private MyRecyclerAdapter mAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        //创建线性布局
        mLayoutManager=new LinearLayoutManager(this);
        //设置布局管理器
        mRecyclerView.setLayoutManager(mLayoutManager);
         //创建适配器,并且设置  
        mAdapter = new MyRecyclerAdapter(this); 
        //设置adapter
        mRecyclerView.setAdapter(mAdapter);
        //设置Item增加、移除动画
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
     
    }

相较于ListView的实现方式,RecyclerView除了相同的一些步骤外,还增加了很多步骤。其实从它类名上可以看出,RecyclerView代表的就是,我只管Recycler View,也就是说RecyclerView只负责回收与复用View,其他的你可以自己去设置。可以看出其高度的解耦,给予你充分的定制自由(所以你才可以轻松的通过这个控件实现ListView,GirdView,瀑布流等效果)。


自定义MyRecyclerAdapter
public class MyRecyclerAdapter extends Adapter<MyRecyclerAdapter.ViewHolder> {
     private List<String> mTitles = null;
    private Context mContext;

    public MyRecyclerAdapter(Context context) {
        super();
        this.mContext = context;
        this.mTitles = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            int index = i + 1;
            mTitles.add("item" + index);
        }
    }

    @Override
    public int getItemCount() {
        return mTitles.size();
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // TODO Auto-generated method stub
        holder.item_tv.setText(mTitles.get(position));
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {
        LayoutInflater inflater=LayoutInflater.from(mContext);
        View view=inflater.inflate(R.layout.item_recycler_layout,parent,false);  
        //view.setBackgroundColor(Color.RED);  
        ViewHolder viewHolder=new ViewHolder(view);  
        return viewHolder;
    }

    // 自定义的ViewHolder,持有每个Item的的所有界面元素
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView item_tv;

        public ViewHolder(View view) {
            super(view);
            item_tv = (TextView) view.findViewById(R.id.item_tv);
        }
    }
}

这个自定义Adapter和我们在使用Listview时候的Adapter相比还是有点不太一样的,首先这边我们需要继承 RecyclerView.Adaper类,然后实现两个重要的方法——onBindViewHodler()以及 onCreateViewHolder(),这边我们看出来区别,使用RecyclerView控件我们就可以把Item View视图创建和数据绑定这两步分开进行管理,用法就更加方便而且灵活了,并且我们可以定制千变万化的布局。同时这边我们还需要创建一个 ViewHolder类,该类必须继承自RecyclerView.ViewHolder类,现在Google也要求我们必须要实现ViewHolder 来承载Item的视图。
现在的实现效果如下:



LinearLayoutManager布局是默认采用垂直布局的,当然我们还可以设置线性布局的方向为横向,只要如下设置即可:
mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

还有两种布局方案,也看下他们的实现方式和效果
GridLayoutManger使用,如下设置
//表格布局
        GridLayoutManager girdLayoutManager=new GridLayoutManager(this,4);  
        mRecyclerView.setLayoutManager(girdLayoutManager);

StaggeredGridLayoutManager 使用,如下设置
//瀑布流式布局
        StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(staggeredGridLayoutManager);

这种写法显示的效果和表格布局是一致的,但是注意StaggeredGridLayoutManager构造的第二个参数是一个orientation,如果传入的是StaggeredGridLayoutManager.VERTICAL代表有多少列;那么传入的如果是StaggeredGridLayoutManager.HORIZONTAL就代表有多少行,比如本例如果改为:

//瀑布流式布局
        StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.HORIZONTAL);
        mRecyclerView.setLayoutManager(staggeredGridLayoutManager);

那么效果就变为:


可以看到,固定为4行,变成了左右滑动。有一点需要注意,如果是横向的时候,item的宽度需要注意去设置, 这就实现了横向滚动的GridView效果

但上面的显示效果还是比较丑,例如就没有分隔线这个效果,当你去找时,你会发现RecyclerView并没有像ListView一样支持divider这样的属性,我们开头说过ItemDecoration(给每一项Item视图添加子View,可以进行画分隔线之类的东西),利用它就可以添加分割线,在代码中如下调用
mRecyclerView.addItemDecoration()
该方法的参数为RecyclerView.ItemDecoration,该类为抽象类,官方目前并没有提供默认的实现类,我们可以创建一个继承RecyclerView.ItemDecoration类来绘制分隔线
我们主要实现以下四个方法:
public static abstract class ItemDecoration { public void onDraw(Canvas c, RecyclerView parent, State state) { onDraw(c, parent); }
public void onDrawOver(Canvas c, RecyclerView parent, State state) {
            onDrawOver(c, parent);
 }
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
            getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),
                    parent);
}

@Deprecated
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
            outRect.set(0, 0, 0, 0);
 }
当我们调用mRecyclerView.addItemDecoration()方法添加decoration的时候,即调用该类的onDraw和onDrawOver方法,然后LayoutManager进行Item布局的时候,会去调用getItemOffset方法来计算每个Item的Decoration合适的尺寸,因此我们其实只要去重写onDraw和getItemOffsets这两个方法就可以实现啦。这里有几点要说明:
    - onDraw方法先于drawChildren
    - onDrawOver在drawChildren之后,一般我们选择复写其中一个即可。
    - getItemOffsets 可以通过outRect.set()为每个Item设置一定的偏移量,主要用于绘制Decorator。

下面我们具体实现一下
public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
    };

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    private Drawable mDivider;

    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent) {

        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }

    }


    public void drawVertical(Canvas c, RecyclerView parent) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}
该实现类可以看到通过读取系统主题中的 android.R.attr.listDivider 作为Item间的分割线,并且支持横向和纵向,获取到listDivider以后,该属性的值是个Drawable,在getItemOffsets中,outRect去设置了绘制的范围。onDraw中实现了真正的绘制。
在原来的代码中添加一句:
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));

该分割线是系统默认的,使用系统的listDivider的好处就是方便我们去随意的改变,该属性我们可以直接声明在styles.xml中:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:listDivider">@drawable/divider_bg</item>
    </style>

然后自己写个drawable即可,下面我们换一种分隔符
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <gradient
        android:centerColor="#ff00ff00"
        android:endColor="#ff0000ff"
        android:startColor="#ffff0000"
        android:type="linear" />
    <size android:height="4dp"/>

</shape>
现在的效果如下:

但是现在这个DividerItemDecoration对于另外两个布局就不适用了,主要是因为它在绘制的时候,比如水平线,针对每个child的取值为:
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
因为每个Item占一行,这样是没问题的。而使用GridLayoutManager时,一行有多个childItem,这样就多次绘制了,并且使用GridLayoutManager时,Item如果为最后一列(则右边无间隔线)或者为最后一行(底部无分割线)。
所以再写个分割线吧

public class DividerGridItemDecoration extends RecyclerView.ItemDecoration
{

    private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
    private Drawable mDivider;

    public DividerGridItemDecoration(Context context)
    {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, State state)
    {

        drawHorizontal(c, parent);
        drawVertical(c, parent);

    }

    private int getSpanCount(RecyclerView parent)
    {
        // 列数
        int spanCount = -1;
        LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {

            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {
            spanCount = ((StaggeredGridLayoutManager) layoutManager)
                    .getSpanCount();
        }
        return spanCount;
    }

    public void drawHorizontal(Canvas c, RecyclerView parent)
    {
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++)
        {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getLeft() - params.leftMargin;
            final int right = child.getRight() + params.rightMargin
                    + mDivider.getIntrinsicWidth();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawVertical(Canvas c, RecyclerView parent)
    {
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++)
        {
            final View child = parent.getChildAt(i);

            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getTop() - params.topMargin;
            final int bottom = child.getBottom() + params.bottomMargin;
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicWidth();

            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
            int childCount)
    {
        LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {
            if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
            {
                return true;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            if (orientation == StaggeredGridLayoutManager.VERTICAL)
            {
                if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
                {
                    return true;
                }
            } else
            {
                childCount = childCount - childCount % spanCount;
                if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
                    return true;
            }
        }
        return false;
    }

    private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
            int childCount)
    {
        LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {
            childCount = childCount - childCount % spanCount;
            if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
                return true;
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            // StaggeredGridLayoutManager 且纵向滚动
            if (orientation == StaggeredGridLayoutManager.VERTICAL)
            {
                childCount = childCount - childCount % spanCount;
                // 如果是最后一行,则不需要绘制底部
                if (pos >= childCount)
                    return true;
            } else
            // StaggeredGridLayoutManager 且横向滚动
            {
                // 如果是最后一行,则不需要绘制底部
                if ((pos + 1) % spanCount == 0)
                {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition,
            RecyclerView parent)
    {
        int spanCount = getSpanCount(parent);
        int childCount = parent.getAdapter().getItemCount();
        if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
        {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
        {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else
        {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(),
                    mDivider.getIntrinsicHeight());
        }
    }
}

走到这一步,本想说,一切顺利,但是,fuck,这居然有一个天大的坑,也不知道是不是鸿洋大神故意给我们挖到坑,真是个无底洞啊,我研究了半天这个代码都没发现错误,但是使用到表格布局时总是没有水平方向的分割线,而使用系统的样式确正常,fuck,还是我们自定义的属性的问题,后来看下面的跟帖终于明白了,我们在定义drawable时,没有定义android:width~,哭了,加上以后一切正常了

监听事件处理
我们知道在ListView使用的时候,该控件给我们提供一个onItemClickListener监听器,这样当我们的item发生触发事件的时候, 会回调相关的方法,以便我们方便处理Item点击事件。对于RecyclerView来讲,非常可惜的是该控件没有给我们提供这样的内置监听器方法, 不过我们可以进行改造实现。我们先来看一下之前我们写得MyRecyclerAdapter中的onCreateViewHolder()方法中的代码:

@Override

    public ViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {

        LayoutInflater inflater=LayoutInflater.from(mContext);

        View view=inflater.inflate(R.layout.item_recycler_layout,parent,false);  

        //view.setBackgroundColor(Color.RED);  

        ViewHolder viewHolder=new ViewHolder(view);  

        return viewHolder;

    }

该方法创建一个ViewHolder,其中承载的就是每一项Item View视图,那么我们可以在view创建出来之后给它进行添加相应的属性或者监听方法,例如:背景颜色,大小,以及点击事件。既然可以这样解决,OK, 我们给View添加一个onClickListener监听器,然后点击的时候回调onClick()方法。同时我们需要自定义一个类似于 onItemClickListener()的监听器来处理。


如下,我们在MyRecyclerAdapter进行修改

public interface OnItemClickLitener

    {

        void onItemClick(View view, int position);

        void onItemLongClick(View view , int position);

    }


    private OnItemClickLitener mOnItemClickLitener;



    public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener)

    {

        this.mOnItemClickLitener = mOnItemClickLitener;

    }


@Override

    public void onBindViewHolder(final MyViewHolder holder, final int position)

    {

        holder.tv.setText(mDatas.get(position));


        if (mOnItemClickLitener != null)

        {

            holder.itemView.setOnClickListener(new OnClickListener()

            {

                @Override

                public void onClick(View v)

                {

                    int pos = holder.getLayoutPosition();

                    mOnItemClickLitener.onItemClick(holder.itemView, pos);

                }

            });


            holder.itemView.setOnLongClickListener(new OnLongClickListener()

            {

                @Override

                public boolean onLongClick(View v)

                {

                    int pos = holder.getLayoutPosition();

                    mOnItemClickLitener.onItemLongClick(holder.itemView, pos);              

                    return false;

                }

            });

        }

    }


Activity中去设置监听:

mAdapter.setOnItemClickLitener(new OnItemClickLitener()

        {

            @Override

            public void onItemClick(View view, int position)

            {

                Toast.makeText(MainActivity.this, position + " click",

                        Toast.LENGTH_SHORT).show();

            }


            @Override

            public void onItemLongClick(View view, int position)

            {

                Toast.makeText(MainActivity.this, position + " long click",

                        Toast.LENGTH_SHORT).show();

            }

        });

效果如下:


数据添加删除处理

现在我们来看一下当数据发生变化之后的处理。例如我们在使用ListView的时候,当数据发生变化的时候可以通过 notifyDatasetChange()来刷新界面。对于RecyclerView控件来讲,给我们提供更加高级的使用方法 notifyItemInserted(position)和notifyItemRemoved(position)

我们可以在MyRecyclerAdapter中添加数据新增和数据删除的方法如下:


public void addItem(int position)

    {

        mTitles.add(position, "Insert One");

        notifyItemInserted(position);

    }



    public void removeItem(int position)

    {

        mTitles.remove(position);

        notifyItemRemoved(position);

    }


之后我们就可以在MainActivity中进行调用了


RecyclerView总结

到此为止就完成我们RecyclerView控件基本使用的说明,其中包括控件的基本介绍,基本使用(系统提供的几种LayoutManager的使用),高级用法(自定义间隔符,加入点击监听事件以及 Item添加删除动画处理),如何添加ItemClickListener与ItemLongClickListener。 总体来讲RecyclerView控件是非常不错,尤其在布局以及数据绑定,动画方面,除了系统内置的三种布局方式之外,我们还可以定制出我们自己的布局管理器。同时当item数据发生变化的时候还给我们提供非常炫的效果


源代码

参考:



相关文章
|
4月前
|
存储 缓存 Android开发
Android RecyclerView 缓存机制深度解析与面试题
本文首发于公众号“AntDream”,详细解析了 `RecyclerView` 的缓存机制,包括多级缓存的原理与流程,并提供了常见面试题及答案。通过本文,你将深入了解 `RecyclerView` 的高性能秘诀,提升列表和网格的开发技能。
85 8
RecyclerView解析--onViewDetachedFromWindow()/onViewAttachedToWindow()
先看这段源码介绍: /** * Called when a view created by this adapter has been detached from its window.
1108 0
|
XML 前端开发 Android开发
Android RecyclerView 使用完全解析 体验艺术般的控件
转自 :http://blog.csdn.net/lmj623565791/article/details/45059587 概述 RecyclerView出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用。  据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、G
1320 0
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
87 2
|
3月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
87 0
|
3月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
68 0
|
12天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
12天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

推荐镜像

更多