RecyclerView 介绍 02 – 重要概念
几个概念
- RecyclerView是一个ViewGroup;
 - LayoutManager控制RecyclerView的ChildView的布局显示,childview由Recycler提供以及管理;
 - Recycler具有两级缓存,Scrap和RecycledViewPool,通过Detach以及Remove,对Viewholder进行转移以及状态改变;
 - RecycledViewPool可以由多个RecyclerView共享;
 - ViewHolder具有多种状态标记;
 
关于Recycler
Scrap中的ViewHolder,不用通过Adapter重新处理,只需要attach后回到LayoutManager就可以重用。
RecycledViewPool中的ViewHolder,数据往往是错误的,则需要通过Adapter重新绑定正确的数据后在回到LayoutManager。
当LayoutManager需要一个新的View时,Recycler会行检查scrap中是否有合适的ViewHolder,如果有直接返回给LayoutManager使用;如果没有,就需要从Pool里面寻找,然后右Adapter重新绑定数据后,返回到LayoutManager;如果pool还是没有,就需要由Adapter创建一个新的Viewholder。见如下代码:
- View getViewForPosition(int position, boolean dryRun) {
 - if (position < 0 || position >= mState.getItemCount()) {
 - throw new IndexOutOfBoundsException("Invalid item position " + position
 - + "(" + position + "). Item count:" + mState.getItemCount());
 - }
 - boolean fromScrap = false;
 - ViewHolder holder = null;
 - // 0) If there is a changed scrap, try to find from there
 - if (mState.isPreLayout()) {
 - holder = getChangedScrapViewForPosition(position);
 - fromScrap = holder != null;
 - }
 - // 1) Find from scrap by position
 - if (holder == null) {
 - holder = getScrapViewForPosition(position, INVALID_TYPE, dryRun);
 - if (holder != null) {
 - if (!validateViewHolderForOffsetPosition(holder)) {
 - // recycle this scrap
 - if (!dryRun) {
 - // we would like to recycle this but need to make sure it is not used by
 - // animation logic etc.
 - holder.addFlags(ViewHolder.FLAG_INVALID);
 - if (holder.isScrap()) {
 - removeDetachedView(holder.itemView, false);
 - holder.unScrap();
 - } else if (holder.wasReturnedFromScrap()) {
 - holder.clearReturnedFromScrapFlag();
 - }
 - recycleViewHolderInternal(holder);
 - }
 - holder = null;
 - } else {
 - fromScrap = true;
 - }
 - }
 - }
 - if (holder == null) {
 - final int offsetPosition = mAdapterHelper.findPositionOffset(position);
 - if (offsetPosition < 0 || offsetPosition >= mAdapter.getItemCount()) {
 - throw new IndexOutOfBoundsException("Inconsistency detected. Invalid item "
 - + "position " + position + "(offset:" + offsetPosition + ")."
 - + "state:" + mState.getItemCount());
 - }
 - final int type = mAdapter.getItemViewType(offsetPosition);
 - // 2) Find from scrap via stable ids, if exists
 - if (mAdapter.hasStableIds()) {
 - holder = getScrapViewForId(mAdapter.getItemId(offsetPosition), type, dryRun);
 - if (holder != null) {
 - // update position
 - holder.mPosition = offsetPosition;
 - fromScrap = true;
 - }
 - }
 - if (holder == null && mViewCacheExtension != null) {
 - // We are NOT sending the offsetPosition because LayoutManager does not
 - // know it.
 - final View view = mViewCacheExtension
 - .getViewForPositionAndType(this, position, type);
 - if (view != null) {
 - holder = getChildViewHolder(view);
 - if (holder == null) {
 - throw new IllegalArgumentException("getViewForPositionAndType returned"
 - + " a view which does not have a ViewHolder");
 - } else if (holder.shouldIgnore()) {
 - throw new IllegalArgumentException("getViewForPositionAndType returned"
 - + " a view that is ignored. You must call stopIgnoring before"
 - + " returning this view.");
 - }
 - }
 - }
 - if (holder == null) { // fallback to recycler
 - // try recycler.
 - // Head to the shared pool.
 - if (DEBUG) {
 - Log.d(TAG, "getViewForPosition(" + position + ") fetching from shared "
 - + "pool");
 - }
 - holder = getRecycledViewPool()
 - .getRecycledView(mAdapter.getItemViewType(offsetPosition));
 - if (holder != null) {
 - holder.resetInternal();
 - if (FORCE_INVALIDATE_DISPLAY_LIST) {
 - invalidateDisplayListInt(holder);
 - }
 - }
 - }
 - if (holder == null) {
 - holder = mAdapter.createViewHolder(RecyclerView.this,
 - mAdapter.getItemViewType(offsetPosition));
 - if (DEBUG) {
 - Log.d(TAG, "getViewForPosition created new ViewHolder");
 - }
 - }
 - }
 - boolean bound = false;
 - if (mState.isPreLayout() && holder.isBound()) {
 - // do not update unless we absolutely have to.
 - holder.mPreLayoutPosition = position;
 - } else if (!holder.isBound() || holder.needsUpdate() || holder.isInvalid()) {
 - if (DEBUG && holder.isRemoved()) {
 - throw new IllegalStateException("Removed holder should be bound and it should"
 - + " come here only in pre-layout. Holder: " + holder);
 - }
 - final int offsetPosition = mAdapterHelper.findPositionOffset(position);
 - mAdapter.bindViewHolder(holder, offsetPosition);
 - attachAccessibilityDelegate(holder.itemView);
 - bound = true;
 - if (mState.isPreLayout()) {
 - holder.mPreLayoutPosition = position;
 - }
 - }
 - final ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
 - final LayoutParams rvLayoutParams;
 - if (lp == null) {
 - rvLayoutParams = (LayoutParams) generateDefaultLayoutParams();
 - holder.itemView.setLayoutParams(rvLayoutParams);
 - } else if (!checkLayoutParams(lp)) {
 - rvLayoutParams = (LayoutParams) generateLayoutParams(lp);
 - holder.itemView.setLayoutParams(rvLayoutParams);
 - } else {
 - rvLayoutParams = (LayoutParams) lp;
 - }
 - rvLayoutParams.mViewHolder = holder;
 - rvLayoutParams.mPendingInvalidate = fromScrap && bound;
 - return holder.itemView;
 - }
 
关于ViewHolder
在RecyclerView里面,view是有多重状态的,各种状态在ViewHolder里面定义。看看下面的代码:
- public static abstract class ViewHolder {
 - public final View itemView;
 - int mPosition = NO_POSITION;
 - int mOldPosition = NO_POSITION;
 - long mItemId = NO_ID;
 - int mItemViewType = INVALID_TYPE;
 - int mPreLayoutPosition = NO_POSITION;
 - // The item that this holder is shadowing during an item change event/animation
 - ViewHolder mShadowedHolder = null;
 - // The item that is shadowing this holder during an item change event/animation
 - ViewHolder mShadowingHolder = null;
 - /**
 - * This ViewHolder has been bound to a position; mPosition, mItemId and mItemViewType
 - * are all valid.
 - */
 - static final int FLAG_BOUND = 1 << 0;
 - /**
 - * The data this ViewHolder's view reflects is stale and needs to be rebound
 - * by the adapter. mPosition and mItemId are consistent.
 - */
 - static final int FLAG_UPDATE = 1 << 1;
 - /**
 - * This ViewHolder's data is invalid. The identity implied by mPosition and mItemId
 - * are not to be trusted and may no longer match the item view type.
 - * This ViewHolder must be fully rebound to different data.
 - */
 - static final int FLAG_INVALID = 1 << 2;
 - /**
 - * This ViewHolder points at data that represents an item previously removed from the
 - * data set. Its view may still be used for things like outgoing animations.
 - */
 - static final int FLAG_REMOVED = 1 << 3;
 - /**
 - * This ViewHolder should not be recycled. This flag is set via setIsRecyclable()
 - * and is intended to keep views around during animations.
 - */
 - static final int FLAG_NOT_RECYCLABLE = 1 << 4;
 - /**
 - * This ViewHolder is returned from scrap which means we are expecting an addView call
 - * for this itemView. When returned from scrap, ViewHolder stays in the scrap list until
 - * the end of the layout pass and then recycled by RecyclerView if it is not added back to
 - * the RecyclerView.
 - */
 - static final int FLAG_RETURNED_FROM_SCRAP = 1 << 5;
 - /**
 - * This ViewHolder's contents have changed. This flag is used as an indication that
 - * change animations may be used, if supported by the ItemAnimator.
 - */
 - static final int FLAG_CHANGED = 1 << 6;
 - /**
 - * This ViewHolder is fully managed by the LayoutManager. We do not scrap, recycle or remove
 - * it unless LayoutManager is replaced.
 - * It is still fully visible to the LayoutManager.
 - */
 - static final int FLAG_IGNORE = 1 << 7;
 
------EOF----------
RecyclerView 介绍 02 – 重要概念的更多相关文章
- C#多线程之旅(1)——介绍和基本概念
		
原文地址:C#多线程之旅(1)——介绍和基本概念 C#多线程之旅目录: C#多线程之旅(1)——介绍和基本概念 C#多线程之旅(2)——创建和开始线程 C#多线程之旅(3)——线程池 C#多线程之旅( ...
 - TensorFlow入门,基本介绍,基本概念,计算图,pip安装,helloworld示例,实现简单的神经网络
		
TensorFlow入门,基本介绍,基本概念,计算图,pip安装,helloworld示例,实现简单的神经网络
 - 01.课程介绍 & 02.最小可行化产品MVP
		
01.课程介绍 02.最小可行化产品MVP 产品开发过程 最小化和可用之间找到一个平衡点
 - vue项目搭建介绍02
		
目录 vue项目搭建介绍02 python-pycharm设置: vue创建项目分类: vue-cli构建 自定义构建 基础的vue项目目录: vue项目搭建介绍02 python-pycharm设置 ...
 - ZooKeeper入门实战教程(一)-介绍与核心概念
		
1.ZooKeeper介绍与核心概念1.1 简介ZooKeeper最为主要的使用场景,是作为分布式系统的分布式协同服务.在学习zookeeper之前,先要对分布式系统的概念有所了解,否则你将完全不知道 ...
 - 黑马_13 Spring Boot:01.spring boot 介绍&&02.spring boot 入门
		
13 Spring Boot: 01.spring boot 介绍&&02.spring boot 入门 04.spring boot 配置文件 SpringBoot基础 1.1 原有 ...
 - 083 01 Android 零基础入门  02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 02 构造方法-带参构造方法
		
083 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 02 构造方法-带参构造方法 本文知识点:构造方法-带参构造方法 说明:因为时间紧张, ...
 - Android新组件RecyclerView介绍,其效率更好
		
今天我们首先来说为什么要介绍这个新组件RecyclerView,因为前几天我发布了一个常用面试题ListView的复用及如何优化的文章,介绍给一些开发者,但是我看到有关的反馈说:现在都不再用listv ...
 - maven使用.02.一些概念
		
在上一篇POST中,简要的介绍了一下maven的特点,优势,安装.并建立了一个简单地Hello world工程.这一篇POST中,将主要会介绍一下Maven的一些约定. pom.xml文件 Maven ...
 
随机推荐
- Divide and Conquer:Cable Master(POJ 1064)
			
缆绳大师 题目大意,把若干线段分成K份,求最大能分多长 二分法模型,C(x)就是题干的意思,在while那里做下文章就可以了,因为这个题目没有要求长度是整数,所以我们要不断二分才行,一般50-100次 ...
 - CSS中的ul与li样式详解
			
CSS中的ul与li样式详解ul和li列表是使用CSS布局页面时常用的元素.在CSS中,有专门控制列表表现的属性,常用的有list-style-type属性.list-style-image属性.li ...
 - Spring mvc中@RequestMapping 6个基本用法小结(转载)
			
小结下spring mvc中的@RequestMapping的用法. 1)最基本的,方法级别上应用,例如: @RequestMapping(value="/departments" ...
 - web开发,关于jsp的常见问题,重复提交,防止后退。
			
看了网上的,有几种方法:1 在你的表单页里HEAD区加入这段代码: <META HTTP-EQUIV="pragma" CONTENT="no-cache" ...
 - NEFU 504 new Flip Game (高斯消元)
			
题目链接 题解:和 poj1753Filp game 差不多,区别在于t组数据并且翻转的时候多了一个左上角. #include <iostream> #include <cstdio ...
 - iOS进阶面试题----多线程
			
1 多线程是什么 多线程是个复杂的概念,按字面意思是同步完成多 项任务,提高了资源的使用效率,从硬件.操作系统.应用软件不同的角度去看,多线程被赋予不同的内涵,对于硬件,现在市面上多数的CPU都是多核 ...
 - objective-c可变字典
			
1 #pragma mark *****************************字典******************************** 2 // 字典:通过ke ...
 - 不同版本CUDA编程的问题
			
1 无法装上CUDA的toolkit 卸载所有的NVIDIA相关的app,包括NVIDIA的显卡驱动,然后重装. 2之前的文件打不开,one or more projects in the solut ...
 - Linear regression with one variable算法实例讲解(绘制图像,cost_Function ,Gradient Desent, 拟合曲线, 轮廓图绘制)_矩阵操作
			
%测试数据 'ex1data1.txt', 第一列为 population of City in 10,000s, 第二列为 Profit in $10,000s 1 6.1101,17.592 5. ...
 - window 环境安装MongoDB
			
强制安装mongodb服务 命令 sc create MongoDB binPath= "D:\MongoDB\Server\3.2\bin\mongod.exe --service --d ...