public VH onCreateViewHolder(ViewGroup parent, int viewType)
建立Item视图,并返回相应的ViewHolder
public void onBindViewHolder(VH holder, int position)
绑定数据到正确的Item视图上。
public int getItemCount()
返回该Adapter所持有的Itme数量
public int getItemViewType(int position)
用来获取当前项Item(position参数)是哪一种类型的布局
复制代码
public final void notifyDataSetChanged() {
mObservable.notifyChanged();
}
复制代码
static class AdapterDataObservable extends Observable<AdapterDataObserver> {
public boolean hasObservers() {
return !mObservers.isEmpty();
}
public void notifyChanged() {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
public void notifyItemRangeChanged(int positionStart, int itemCount) {
notifyItemRangeChanged(positionStart, itemCount, null);
}
public void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onItemRangeChanged(positionStart, itemCount, payload);
}
}
public void notifyItemRangeInserted(int positionStart, int itemCount) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onItemRangeInserted(positionStart, itemCount);
}
}
}
复制代码
public static abstract class AdapterDataObserver {
public void onChanged() {
// Do nothing
}
public void onItemRangeChanged(int positionStart, int itemCount) {
// do nothing
}
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
onItemRangeChanged(positionStart, itemCount);
}
}
复制代码
public void setAdapter(Adapter adapter) {
// bail out if layout is frozen
setLayoutFrozen(false);
setAdapterInternal(adapter, false, true);
requestLayout();
}
复制代码
private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious,
boolean removeAndRecycleViews) {
if (mAdapter != null) {
mAdapter.unregisterAdapterDataObserver(mObserver);
mAdapter.onDetachedFromRecyclerView(this);
}
if (!compatibleWithPrevious || removeAndRecycleViews) {
removeAndRecycleViews();
}
mAdapterHelper.reset();
final Adapter oldAdapter = mAdapter;
mAdapter = adapter;
if (adapter != null) {
//注册一个观察者RecyclerViewDataObserver
adapter.registerAdapterDataObserver(mObserver);
adapter.onAttachedToRecyclerView(this);
}
if (mLayout != null) {
mLayout.onAdapterChanged(oldAdapter, mAdapter);
}
mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
mState.mStructureChanged = true;
markKnownViewsInvalid();
}
复制代码
public final VH createViewHolder(ViewGroup parent, int viewType) {
TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG);
final VH holder = onCreateViewHolder(parent, viewType);
holder.mItemViewType = viewType;
TraceCompat.endSection();
return holder;
}
复制代码
public View getViewForPosition(int position) {
return getViewForPosition(position, false);
}
View getViewForPosition(int position, boolean dryRun) {
return tryGetViewHolderForPositionByDeadline(position, dryRun, FOREVER_NS).itemView;
}
@Nullable
ViewHolder tryGetViewHolderForPositionByDeadline(int position,boolean dryRun, long deadlineNs) {
//代码省略了,有须要的小伙伴能够本身看看,这里面逻辑实在太复杂呢
}
复制代码
class MyViewHolder extends RecyclerView.ViewHolder {
private SparseArray<View> viewSparseArray;
private TextView tvTitle;
MyViewHolder(final View itemView) {
super(itemView);
if(viewSparseArray==null){
viewSparseArray = new SparseArray<>();
}
tvTitle = (TextView) viewSparseArray.get(R.id.tv_title);
if (tvTitle == null) {
tvTitle = itemView.findViewById(R.id.tv_title);
viewSparseArray.put(R.id.tv_title, tvTitle);
}
}
}
复制代码
public void setLayoutManager(LayoutManager layout) {
if (layout == mLayout) {
return;
}
// 中止滑动
stopScroll();
if (mLayout != null) {
// 若是有动画,则中止全部的动画
if (mItemAnimator != null) {
mItemAnimator.endAnimations();
}
// 移除并回收视图
mLayout.removeAndRecycleAllViews(mRecycler);
// 回收废弃视图
mLayout.removeAndRecycleScrapInt(mRecycler);
//清除mRecycler
mRecycler.clear();
if (mIsAttached) {
mLayout.dispatchDetachedFromWindow(this, mRecycler);
}
mLayout.setRecyclerView(null);
mLayout = null;
} else {
mRecycler.clear();
}
mChildHelper.removeAllViewsUnfiltered();
mLayout = layout;
if (layout != null) {
if (layout.mRecyclerView != null) {
throw new IllegalArgumentException("LayoutManager " + layout +
" is already attached to a RecyclerView: " + layout.mRecyclerView);
}
mLayout.setRecyclerView(this);
if (mIsAttached) {
mLayout.dispatchAttachedToWindow(this);
}
}
//更新新的缓存数据
mRecycler.updateViewCacheSize();
//从新请求 View 的测量、布局、绘制
requestLayout();
}
复制代码
LinearSnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(mRecyclerView);
复制代码
PagerSnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(mRecyclerView);
复制代码
GridLayoutManager manager = new GridLayoutManager(this, 6);
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
SpanModel model = mDataList.get(position);
if (model.getType() == 1) {
return 6;
} else if(model.getType() == 2){
return 3;
}else if (model.getType() == 3){
return 2;
}else if (model.getType() == 4){
return 2;
} else {
return 1;
}
}
});
复制代码
public void onDraw(Canvas c, RecyclerView parent)
装饰的绘制在Item条目绘制以前调用,因此这有可能被Item的内容所遮挡
public void onDrawOver(Canvas c, RecyclerView parent)
装饰的绘制在Item条目绘制以后调用,所以装饰将浮于Item之上
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent)
与padding或margin相似,LayoutManager在测量阶段会调用该方法,计算出每个Item的正确尺寸并设置偏移量。
复制代码
public void addItemDecoration(ItemDecoration decor) {
addItemDecoration(decor, -1);
}
//主要看这个方法,个人GitHub:https://github.com/yangchong211/YCBlogs
public void addItemDecoration(ItemDecoration decor, int index) {
if (mLayout != null) {
mLayout.assertNotInLayoutOrScroll("Cannot add item decoration during a scroll or"
+ " layout");
}
if (mItemDecorations.isEmpty()) {
setWillNotDraw(false);
}
if (index < 0) {
mItemDecorations.add(decor);
} else {
// 指定添加分割线在集合中的索引
mItemDecorations.add(index, decor);
}
markItemDecorInsetsDirty();
// 从新请求 View 的测量、布局、绘制
requestLayout();
}
复制代码
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
// 若是当前是footer的位置,那么该item占据2个单元格,正常状况下占据1个单元格
return getItemViewType(position) == footType ? gridManager.getSpanCount() : 1;
}
});
}
}
复制代码
RecyclerView
以LinearLayoutManager为例
忽略ItemDecoration
忽略ItemAnimator
忽略Measure过程
假设RecyclerView的width和height是肯定的
Recycler
忽略mViewCacheExtension
复制代码
public final class Recycler {
final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
ArrayList<ViewHolder> mChangedScrap = null;
final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
private final List<ViewHolder>
mUnmodifiableAttachedScrap = Collections.unmodifiableList(mAttachedScrap);
private int mRequestedCacheMax = DEFAULT_CACHE_SIZE;
int mViewCacheMax = DEFAULT_CACHE_SIZE;
RecycledViewPool mRecyclerPool;
private ViewCacheExtension mViewCacheExtension;
static final int DEFAULT_CACHE_SIZE = 2;
}
复制代码
@SuppressWarnings("WeakerAccess")
@Nullable
public abstract int[] calculateDistanceToFinalSnap(@NonNull LayoutManager layoutManager,
@NonNull View targetView);
复制代码
@SuppressWarnings("WeakerAccess")
@Nullable
public abstract View findSnapView(LayoutManager layoutManager);
复制代码
public abstract int findTargetSnapPosition(LayoutManager layoutManager, int velocityX,
int velocityY);
复制代码
SnapHelper继承了 RecyclerView.OnFlingListener,实现了onFling方法。android
@Override
public boolean onFling(int velocityX, int velocityY) {
LayoutManager layoutManager = mRecyclerView.getLayoutManager();
if (layoutManager == null) {
return false;
}
RecyclerView.Adapter adapter = mRecyclerView.getAdapter();
if (adapter == null) {
return false;
}
int minFlingVelocity = mRecyclerView.getMinFlingVelocity();
return (Math.abs(velocityY) > minFlingVelocity || Math.abs(velocityX) > minFlingVelocity)
&& snapFromFling(layoutManager, velocityX, velocityY);
}
复制代码
接着看看snapFromFling方法源代码,就是经过该方法实现平滑滚动并使得在滚动中止时itemView对齐到目的坐标位置git
private boolean snapFromFling(@NonNull LayoutManager layoutManager, int velocityX,
int velocityY) {
if (!(layoutManager instanceof ScrollVectorProvider)) {
return false;
}
RecyclerView.SmoothScroller smoothScroller = createSnapScroller(layoutManager);
if (smoothScroller == null) {
return false;
}
int targetPosition = findTargetSnapPosition(layoutManager, velocityX, velocityY);
if (targetPosition == RecyclerView.NO_POSITION) {
return false;
}
smoothScroller.setTargetPosition(targetPosition);
layoutManager.startSmoothScroll(smoothScroller);
return true;
}
复制代码
接着看下createSnapScroller这个方法源码博客程序员
@Nullable
protected LinearSmoothScroller createSnapScroller(LayoutManager layoutManager) {
if (!(layoutManager instanceof ScrollVectorProvider)) {
return null;
}
return new LinearSmoothScroller(mRecyclerView.getContext()) {
@Override
protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
int[] snapDistances = calculateDistanceToFinalSnap(mRecyclerView.getLayoutManager(),
targetView);
final int dx = snapDistances[0];
final int dy = snapDistances[1];
final int time = calculateTimeForDeceleration(Math.max(Math.abs(dx), Math.abs(dy)));
if (time > 0) {
action.update(dx, dy, time, mDecelerateInterpolator);
}
}
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}
};
}
复制代码
@Override
public int[] calculateDistanceToFinalSnap(
@NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView) {
int[] out = new int[2];
if (layoutManager.canScrollHorizontally()) {
out[0] = distanceToCenter(layoutManager, targetView,
getHorizontalHelper(layoutManager));
} else {
out[0] = 0;
}
if (layoutManager.canScrollVertically()) {
out[1] = distanceToCenter(layoutManager, targetView,
getVerticalHelper(layoutManager));
} else {
out[1] = 0;
}
return out;
}
复制代码
private int distanceToCenter(@NonNull RecyclerView.LayoutManager layoutManager,
@NonNull View targetView, OrientationHelper helper) {
final int childCenter = helper.getDecoratedStart(targetView)
+ (helper.getDecoratedMeasurement(targetView) / 2);
final int containerCenter;
if (layoutManager.getClipToPadding()) {
containerCenter = helper.getStartAfterPadding() + helper.getTotalSpace() / 2;
} else {
containerCenter = helper.getEnd() / 2;
}
return childCenter - containerCenter;
}
复制代码
//获取当前view的位置信息,该方法主要是设置条目周边的偏移量
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state)
//在item背后draw
public void onDraw(Canvas c, RecyclerView parent, State state)
//在item上边draw
public void onDrawOver(Canvas c, RecyclerView parent, State state)
复制代码
public class HomeAdapter extends RecyclerView.Adapter {
public static final int TYPE_BANNER = 0;
public static final int TYPE_AD = 1;
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType){
case TYPE_BANNER:
return new BannerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.home_banner_layout,null));
case TYPE_AD:
return new BannerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.home_ad_item_layout,null));
}
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int type = getItemViewType(position);
switch (type){
case TYPE_BANNER:
// banner 逻辑处理
break;
case TYPE_AD:
// 广告逻辑处理
break;
// ... 此处省去N行代码
}
}
@Override
public int getItemViewType(int position) {
if(position == 0){
return TYPE_BANNER;//banner在开头
}else {
return mData.get(position).type;//type 的值为TYPE_AD,TYPE_IMAGE,TYPE_AD,等其中一个
}
}
public static class BannerViewHolder extends RecyclerView.ViewHolder{
public BannerViewHolder(View itemView) {
super(itemView);
}
}
public static class NewViewHolder extends RecyclerView.ViewHolder{
public VideoViewHolder(View itemView) {
super(itemView);
}
}
}
复制代码
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.item_me_gv_grid, parent, false);
final MyViewHolder holder = new MyViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
listener.onItemClick(view, holder.getLayoutPosition());
}
}
});
return holder;
}
复制代码
@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
listener.onItemClick(holder.itemView, holder.getAdapterPosition());
}
}
});
}
复制代码
//RecyclerView.SCROLL_STATE_IDLE //空闲状态
//RecyclerView.SCROLL_STATE_FLING //滚动状态
//RecyclerView.SCROLL_STATE_TOUCH_SCROLL //触摸后状态
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
LoggerUtils.e("initRecyclerView"+ "恢复Glide加载图片");
Glide.with(ImageBrowseActivity.this).resumeRequests();
}else {
LoggerUtils.e("initRecyclerView"+"禁止Glide加载图片");
Glide.with(ImageBrowseActivity.this).pauseRequests();
}
}
});
复制代码
beforeDescendants:viewgroup会优先其子类控件而获取到焦点
afterDescendants:viewgroup只有当其子类控件不须要获取焦点时才获取焦点
blocksDescendants:viewgroup会覆盖子类控件而直接得到焦点
复制代码
public class NoNestedScrollview extends NestedScrollView {
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
int action = e.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
downX = (int) e.getRawX();
downY = (int) e.getRawY();
break;
case MotionEvent.ACTION_MOVE:
//判断是否滑动,若滑动就拦截事件
int moveY = (int) e.getRawY();
if (Math.abs(moveY - downY) > mTouchSlop) {
return true;
}
break;
default:
break;
}
return super.onInterceptTouchEvent(e);
}
}
复制代码
recyclerView.setLayoutManager(new GridLayoutManager(mContext,2){
@Override
public boolean canScrollVertically() {
return false;
}
@Override
public boolean canScrollHorizontally() {
return super.canScrollHorizontally();
}
});
recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayout.VERTICAL,false){
@Override
public boolean canScrollVertically() {
return false;
}
});
复制代码
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_hot_review"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foregroundGravity="center" />
</RelativeLayout>
复制代码
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
/*---解决垂ViewPager嵌套直RecyclerView嵌套水平RecyclerView横向滑动到底后不滑动ViewPager start ---*/
ViewParent parent = this;
while(!((parent = parent.getParent()) instanceof ViewPager));
// 循环查找viewPager
parent.requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(ev);
}
复制代码
//给ImageView打上Tag做为特有标记
imageView.setTag(tag);
//下载图片
loadImage();
//根据tag判断是否是须要设置给ImageView
if(tag == iamgeView.getTag()) {
imageView.setBitmapImage(iamge);
}
复制代码