最后
针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。
上述的面试题答案都整理成文档笔记。 也还整理了一些面试资料&最新2021收集的一些大厂的面试真题(都整理成文档,小部分截图)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
this.mContext = parent.getContext();
this.mLayoutInflater = LayoutInflater.from(mContext);
switch (viewType) {
case LOADING_VIEW:
baseViewHolder = getLoadingView(parent);
break;
case HEADER_VIEW:
baseViewHolder = createBaseViewHolder(mHeaderLayout);
break;
case EMPTY_VIEW:
baseViewHolder = createBaseViewHolder(mEmptyLayout);
break;
case FOOTER_VIEW:
baseViewHolder = createBaseViewHolder(mFooterLayout);
break;
default:
baseViewHolder = onCreateDefViewHolder(parent, viewType);
bindViewClickListener(baseViewHolder);
}
baseViewHolder.setAdapter(this);
return baseViewHolder;
}
/**
-
创建默认的ViewHolder 即中间的数据项的ViewHolder
-
@param parent
-
@param viewType
-
@return
*/
protected K onCreateDefViewHolder(ViewGroup parent, int viewType) {
int layoutId = mLayoutResId;
if (mMultiTypeDelegate != null) { //不同的类型的布局
layoutId = mMultiTypeDelegate.getLayoutId(viewType);
}
return createBaseViewHolder(parent, layoutId);
}
protected K createBaseViewHolder(ViewGroup parent, int layoutResId) {
return createBaseViewHolder(getItemView(layoutResId, parent));
}
/**
-
@param layoutResId ID for an XML layout resource to load
-
@param parent Optional view to be the parent of the generated hierarchy or else
-
simply an object that
-
provides a set of LayoutParams values for root of the returned
-
hierarchy
-
@return view will be return
*/
protected View getItemView(@LayoutRes int layoutResId, ViewGroup parent) {
return mLayoutInflater.inflate(layoutResId, parent, false);
}
不管是什么类型,最终都会创建BaseViewHolder的对象.
然后通过createBaseViewHolder()方法去创建.我们稍后再来看看createBaseViewHolder()方法.先看看onCreateDefViewHolder()方法.它是数据项创建ViewHolder,比较”特殊”.
如果是默认类型的,则调用onCreateDefViewHolder(),判断是否是多布局,然后走下面的逻辑.
-
多布局->则交给多布局的逻辑去获取layoutId
-
不是多布局,通过注解拿来用
最后需要调用getItemView()方法来创建一个View,
其实就是通过LayoutInflater来创建View,这和我们平时一样嘛,哈哈.
/**
-
if you want to use subclass of BaseViewHolder in the adapter,
-
you must override the method to create new ViewHolder.
-
如果要在适配器中使用BaseViewHolder的子类,
-
*您必须覆盖该方法才能创建新的ViewHolder。
-
@param view view
-
@return new ViewHolder
*/
@SuppressWarnings(“unchecked”)
protected K createBaseViewHolder(View view) {
Class temp = getClass();
Class z = null;
while (z == null && null != temp) {
//判断z是否是BaseViewHolder的子类或接口 不是则返回null
z = getInstancedGenericKClass(temp);
//返回超类
temp = temp.getSuperclass();
}
K k;
// 泛型擦除会导致z为null
if (z == null) {
//为null则说明z不是BaseViewHolder的子类或接口 则创建一个BaseViewHolder
k = (K) new BaseViewHolder(view);
} else {
//尝试创建z的实例 利用反射
k = createGenericKInstance(z, view);
}
return k != null ? k : (K) new BaseViewHolder(view);
}
/**
-
get generic parameter K
-
判断z是否是BaseViewHolder的子类或接口
-
@param z
-
@return
*/
private Class getInstancedGenericKClass(Class z) {
//getGenericSuperclass()获得带有泛型的父类
//Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
Type type = z.getGenericSuperclass();
if (type instanceof ParameterizedType) {
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
for (Type temp : types) {
//判断tempClass是否是BaseViewHolder类型相同或具有相同的接口
if (temp instanceof Class) {
Class tempClass = (Class) temp;
if (BaseViewHolder.class.isAssignableFrom(tempClass)) {
return tempClass;
}
} else if (temp instanceof ParameterizedType) {
Type rawType = ((ParameterizedType) temp).getRawType();
if (rawType instanceof Class && BaseViewHolder.class.isAssignableFrom(
(Class<?>) rawType)) {
return (Class<?>) rawType;
}
}
}
}
return null;
}
/**
-
try to create Generic K instance
-
尝试创建Generic K实例
-
@param z
-
@param view
-
@return
*/
@SuppressWarnings(“unchecked”)
private K createGenericKInstance(Class z, View view) {
try {
Constructor constructor;
// inner and unstatic class
//成员类&&非静态类
if (z.isMemberClass() && !Modifier.isStatic(z.getModifiers())) {
//获取z的构造函数
constructor = z.getDeclaredConstructor(getClass(), View.class);
//禁止java语言访问检查
constructor.setAccessible(true);
//通过构造方法构造z对象
return (K) constructor.newInstance(this, view);
} else {
constructor = z.getDeclaredConstructor(View.class);
constructor.setAccessible(true);
return (K) constructor.newInstance(view);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
其实这一大段代码其实是在创建BaseViewHolder的实例,首先是判断是否是BaseViewHolder的子类,如果不是则直接创建BaseViewHolder;如果是则通过反射去创建BaseViewHolder实例.
添加header
/**
-
Append header to the rear of the mHeaderLayout.
-
默认添加header到headerLayout的底部(索引最大的那个位置)
-
@param header
*/
public int addHeaderView(View header) {
return addHeaderView(header, -1);
}
/**
-
Add header view to mHeaderLayout and set header view position in mHeaderLayout.
-
When index = -1 or index >= child count in mHeaderLayout,
-
the effect of this method is the same as that of {@link #addHeaderView(View)}.
-
@param header
-
@param index the position in mHeaderLayout of this header.
-
When index = -1 or index >= child count in mHeaderLayout,
-
the effect of this method is the same as that of {@link #addHeaderView(View)}.
*/
public int addHeaderView(View header, int index) {
return addHeaderView(header, index, LinearLayout.VERTICAL);
}
/**
-
@param header
-
@param index
-
@param orientation
*/
public int addHeaderView(View header, int index, int orientation) {
// 如果为空 则创建头布局
if (mHeaderLayout == null) {
mHeaderLayout = new LinearLayout(header.getContext());
// 方向 LayoutParams设置
if (orientation == LinearLayout.VERTICAL) {
mHeaderLayout.setOrientation(LinearLayout.VERTICAL);
mHeaderLayout.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT));
} else {
mHeaderLayout.setOrientation(LinearLayout.HORIZONTAL);
mHeaderLayout.setLayoutParams(new LayoutParams(WRAP_CONTENT, MATCH_PARENT));
}
}
final int childCount = mHeaderLayout.getChildCount();
// 如果index不合法,则添加到索引最大的位置
if (index < 0 || index > childCount) {
index = childCount;
}
mHeaderLayout.addView(header, index); //就是添加到LinearLayout中嘛,哈哈,被我猜中啦
/*
如果头布局(LinearLayout)中子View(header的item)的数量等于1
说明这是第一次添加headerLayout进RecyclerView
需要进行通知刷新操作 告知RecyclerView第一个索引处更新啦
*/
if (mHeaderLayout.getChildCount() == 1) {
int position = getHeaderViewPosition();
if (position != -1) {
notifyItemInserted(position); //告知RecyclerView第一个索引处更新啦
// 这时RecyclerView中的第一项已经是headerLayout(LinearLayout)了
}
}
return index;
}
public int setHeaderView(View header) {
return setHeaderView(header, 0, LinearLayout.VERTICAL);
}
public int setHeaderView(View header, int index) {
return setHeaderView(header, index, LinearLayout.VERTICAL);
}
public int setHeaderView(View header, int index, int orientation) {
if (mHeaderLayout == null || mHeaderLayout.getChildCount() <= index) {
return addHeaderView(header, index, orientation);
} else {
mHeaderLayout.removeViewAt(index);
mHeaderLayout.addView(header, index);
return index;
}
}
别被吓到了,这次的代码有点多,我们一个一个来分析.添加headrView最终都会到达addHeaderView(View header, int index, int orientation)方法,所以我们直接来分析该方法即可.
1.首先是判断是否初始化了mHeaderLayout(header的布局容器LinearLayout,所有的headerView都放在这里的),没有初始化则创建mHeaderLayout
-
设置LinearLayout方向
-
设置LayoutParams
2.判断headerView的插入位置是否合法
-
合法:插入到应该在的位置
-
不合法:插入到索引最大的位置
3.判断是否是第一次添加headerView
- 如果头布局(LinearLayout)中子View(header的item)的数量等于1,
说明这是第一次添加headerLayout进RecyclerView;
需要进行通知刷新操作,告知RecyclerView第一个索引处更新啦;
- 如若不是第一次添加headerView,则添加到LinearLayout中相应位置就不用管了,因为整个LinearLayout在RecyclerView只占用一个位置,不用通知RecyclerView进行刷新操作.
4.后面的setXXX()方法,其实没什么用吧,差不多就是对前面方法改个名字.
添加footer
/**
-
Append footer to the rear of the mFooterLayout.
-
@param footer
*/
public int addFooterView(View footer) {
return addFooterView(footer, -1, LinearLayout.VERTICAL);
}
public int addFooterView(View footer, int index) {
return addFooterView(footer, index, LinearLayout.VERTICAL);
}
/**
-
Add footer view to mFooterLayout and set footer view position in mFooterLayout.
-
When index = -1 or index >= child count in mFooterLayout,
-
the effect of this method is the same as that of {@link #addFooterView(View)}.
-
@param footer
-
@param index the position in mFooterLayout of this footer.
-
When index = -1 or index >= child count in mFooterLayout,
-
the effect of this method is the same as that of {@link #addFooterView(View)}.
*/
public int addFooterView(View footer, int index, int orientation) {
if (mFooterLayout == null) {
mFooterLayout = new LinearLayout(footer.getContext());
if (orientation == LinearLayout.VERTICAL) {
mFooterLayout.setOrientation(LinearLayout.VERTICAL);
mFooterLayout.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT));
} else {
mFooterLayout.setOrientation(LinearLayout.HORIZONTAL);
mFooterLayout.setLayoutParams(new LayoutParams(WRAP_CONTENT, MATCH_PARENT));
}
}
final int childCount = mFooterLayout.getChildCount();
if (index < 0 || index > childCount) {
index = childCount;
}
mFooterLayout.addView(footer, index);
if (mFooterLayout.getChildCount() == 1) {
int position = getFooterViewPosition();
if (position != -1) {
notifyItemInserted(position);
}
}
return index;
}
public int setFooterView(View header) {
return setFooterView(header, 0, LinearLayout.VERTICAL);
}
public int setFooterView(View header, int index) {
return setFooterView(header, index, LinearLayout.VERTICAL);
}
public int setFooterView(View header, int index, int orientation) {
if (mFooterLayout == null || mFooterLayout.getChildCount() <= index) {
return addFooterView(header, index, orientation);
} else {
mFooterLayout.removeViewAt(index);
mFooterLayout.addView(header, index);
return index;
}
}
这里的代码和前面添加header的逻辑一样的嘛,这里就不多说了.
移除header和footer
/**
-
remove header view from mHeaderLayout.
-
When the child count of mHeaderLayout is 0, mHeaderLayout will be set to null.
-
@param header
*/
public void removeHeaderView(View header) {
if (getHeaderLayoutCount() == 0) return;
mHeaderLayout.removeView(header);
//如果mHeaderLayout已经没有子View,则直接将mHeaderLayout从RecyclerView中移除
if (mHeaderLayout.getChildCount() == 0) {
int position = getHeaderViewPosition();
if (position != -1) {
notifyItemRemoved(position);
}
}
}
/**
-
remove footer view from mFooterLayout,
-
When the child count of mFooterLayout is 0, mFooterLayout will be set to null.
-
@param footer
*/
public void removeFooterView(View footer) {
if (getFooterLayoutCount() == 0) return;
mFooterLayout.removeView(footer);
//如果mFooterLayout已经没有子View,则直接将mHeaderLayout从RecyclerView中移除
if (mFooterLayout.getChildCount() == 0) {
int position = getFooterViewPosition();
if (position != -1) {
notifyItemRemoved(position);
}
}
}
/**
-
remove all header view from mHeaderLayout and set null to mHeaderLayout
-
移除所有header view
*/
public void removeAllHeaderView() {
if (getHeaderLayoutCount() == 0) return;
mHeaderLayout.removeAllViews();
int position = getHeaderViewPosition();
if (position != -1) {
notifyItemRemoved(position);
}
}
/**
-
remove all footer view from mFooterLayout and set null to mFooterLayout
-
移除所有footer view
*/
public void removeAllFooterView() {
if (getFooterLayoutCount() == 0) return;
mFooterLayout.removeAllViews();
int position = getFooterViewPosition();
if (position != -1) {
notifyItemRemoved(position);
}
}
/**
-
返回HeaderView在RecyclerView中的位置
-
@return 0 or -1
*/
private int getHeaderViewPosition() {
//Return to header view notify position
if (getEmptyViewCount() == 1) {
//有空布局 并且 头布局可见
if (mHeadAndEmptyEnable) {
return 0;
}
} else {
//没有空布局 返回0
return 0;
}
return -1;
分享
首先分享一份学习大纲,内容较多,涵盖了互联网行业所有的流行以及核心技术,以截图形式分享:
(亿级流量性能调优实战+一线大厂分布式实战+架构师筑基必备技能+设计思想开源框架解读+性能直线提升架构技术+高效存储让项目性能起飞+分布式扩展到微服务架构…实在是太多了)
其次分享一些技术知识,以截图形式分享一部分:
Tomcat架构解析:
算法训练+高分宝典:
Spring Cloud+Docker微服务实战:
最后分享一波面试资料:
切莫死记硬背,小心面试官直接让你出门右拐
1000道互联网Java面试题:
Java高级架构面试知识整理:
ion() {
//Return to header view notify position
if (getEmptyViewCount() == 1) {
//有空布局 并且 头布局可见
if (mHeadAndEmptyEnable) {
return 0;
}
} else {
//没有空布局 返回0
return 0;
}
return -1;
分享
首先分享一份学习大纲,内容较多,涵盖了互联网行业所有的流行以及核心技术,以截图形式分享:
(亿级流量性能调优实战+一线大厂分布式实战+架构师筑基必备技能+设计思想开源框架解读+性能直线提升架构技术+高效存储让项目性能起飞+分布式扩展到微服务架构…实在是太多了)
其次分享一些技术知识,以截图形式分享一部分:
Tomcat架构解析:
[外链图片转存中…(img-uIu4jK4V-1715812690105)]
算法训练+高分宝典:
[外链图片转存中…(img-gks1LdY1-1715812690106)]
Spring Cloud+Docker微服务实战:
[外链图片转存中…(img-H7653CKH-1715812690106)]
最后分享一波面试资料:
切莫死记硬背,小心面试官直接让你出门右拐
1000道互联网Java面试题:
[外链图片转存中…(img-kgyrfzYq-1715812690106)]
Java高级架构面试知识整理:
[外链图片转存中…(img-w2AproU8-1715812690107)]