先提出一个问题 在listView绘制完成后 从contentView中能findViewById到item里面的view么?
答案是:肯定的
要是你很明确的知道这个问题的,那就不用看了 哈哈
先阐述下我为什么会发现这个问题呢?就是利用ButterKnife是发现的一个问题。
问题的引入
ButterKnife+ListView 这个我在加头的时候是可以的利用ButterKnife可以找到头里面的id的
ButterKnife+RecycleView 这个我在加头的时候是可以的利用ButterKnife是找不到头里面的id的
RecycleView是不自带addheaderView和addFooterView的 这里的实现是想添加一item的原理 实现的
为什么找不到呢 ? 找不到就用不了ButterKnife 用不了不就不能平滑过度我原有的代码了。 虽然感觉到可能平滑过度不了了。不过还是不死心呀。然后我就看了下RecycleView和ListView的源码
RecycleView
java.lang.Object
↳ android.view.View
↳ android.view.ViewGroup
↳ android.support.v7.widget.RecyclerView
ListvView
java.lang.Object
↳ android.view.View
↳ android.view.ViewGroup
↳ android.widget.AdapterView
↳ android.widget.AbsListView
↳ android.widget.ListView
从上面的结论得出 丫的俩玩意血缘上没啥关系
RecycleView没有addHeaderView方法那就看看ListView的是怎么实现的
public void addHeaderView(View v, Object data, boolean isSelectable) {
final FixedViewInfo info = new FixedViewInfo();
info.view = v;
info.data = data;
info.isSelectable = isSelectable;
mHeaderViewInfos.add(info);
mAreAllItemsSelectable &= isSelectable;
// Wrap the adapter if it wasn't already wrapped.
if (mAdapter != null) {
if (!(mAdapter instanceof HeaderViewListAdapter)) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
}
// In the case of re-adding a header view, or adding one later on,
// we need to notify the observer.
if (mDataSetObserver != null) {
mDataSetObserver.onChanged();
}
}
}
上面的 mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter); 这一句很明显 是重新构建了一个adapter 替换原有的adapter
Ps:RecycleView与ListView都是利用adapter进行绘制的 为啥ListView在设置完Adapter后可以find到item里面viiew的id呢?
看源码吧
ListView源码里居然没有onDraw实现方式 AbsListView也没有 那就看onLayout吧
/**
* Subclasses should NOT override this method but
* {@link #layoutChildren()} instead.
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mInLayout = true;
final int childCount = getChildCount();
if (changed) {
for (int i = 0; i < childCount; i++) {
getChildAt(i).forceLayout();
}
mRecycler.markChildrenDirty();
}
layoutChildren();
mInLayout = false;
mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
// TODO: Move somewhere sane. This doesn't belong in onLayout().
if (mFastScroll != null) {
mFastScroll.onItemCountChanged(getChildCount(), mItemCount);
}
}
又调回了子类的layoutChild 然后的就不说了 随便找个将listView源码的博客就能知道 listView 不负责自布局的绘制 而是在布局的时候就将子布局加进去了 说白了在setContentView的时候 会调用布局layout 这个时候item就已经进去的 所以findview肯定能发现id的
然而RecycleView是有onDraw的
@Override
public void onDraw(Canvas c) {
super.onDraw(c);
final int count = mItemDecorations.size();
for (int i = 0; i < count; i++) {
mItemDecorations.get(i).onDraw(c, this, mState);
}
}
它解耦的好 所以他是利用mItemDecorations这玩意绘制的,回想起来用法貌似LayoutManager才是定位的东东哦 所以RecycleView 充分解耦 他是绘制上去的而不是布局上去的
这时候问题就来了 我在使用listView+ButterKnife的时候是可以直接find到headerView里面的Id find的是第一个 正好是加头里面的 id
但是RecyckeView+ButterKnife 就find不到id 无论是第几个
因为Recycle是绘上去的!!!
上述的纯属个人理解,如有不对的地方还请指正。我还及时改正以防误人子弟及改正自己的认知错误