Skip to content

Commit

Permalink
完善代码案例
Browse files Browse the repository at this point in the history
  • Loading branch information
yangchong211 committed Oct 17, 2021
1 parent 2c6fd7f commit 6dc60bb
Show file tree
Hide file tree
Showing 34 changed files with 8,422 additions and 0 deletions.
169 changes: 169 additions & 0 deletions ReadMeWiki/01.RecyclerView.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#### 目录介绍
- 01.RecyclerView的结构
- 02.RecyclerView简单用法
- 03.RecyclerView思路


### 好消息
- 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计N篇[近100万字,陆续搬到网上],转载请注明出处,谢谢!
- **链接地址:https://github.com/yangchong211/YCBlogs**
- 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!




### 01.RecycleView的结构
- 关于RecyclerView,大家都已经很熟悉了,用途十分广泛,大概结构如下所示
* RecyclerView.Adapter - 处理数据集合并负责绑定视图
* ViewHolder - 持有所有的用于绑定数据或者需要操作的View
* LayoutManager - 负责摆放视图等相关操作
* ItemDecoration - 负责绘制Item附近的分割线
* ItemAnimator - 为Item的一般操作添加动画效果,如,增删条目等
- 如图所示,直观展示结构
- ![image](https://upload-images.jianshu.io/upload_images/4432347-6301e0c8563ecda0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)



### 02.RecyclerView简单用法[博客](https://github.com/yangchong211/YCBlogs)
- 针对上面几个属性,最简单用法如下所示
```
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
//设置layoutManager
recyclerView.setLayoutManager(layoutManager);
final RecycleViewItemLine line = new RecycleViewItemLine(this, LinearLayout.HORIZONTAL,1,this.getResources().getColor(R.color.colorAccent));
//设置添加分割线
recyclerView.addItemDecoration(line);
adapter = new MultipleItemAdapter(this);
//设置adapter
recyclerView.setAdapter(adapter);
//添加数据并且刷新adapter
adapter.addAll(list);
adapter.notifyDataSetChanged();
//adapter
//onCreateViewHolder(ViewGroup parent, int viewType)这里的第二个参数就是View的类型,可以根据这个类型判断去创建不同item的ViewHolder
public class MultipleItemAdapter extends RecyclerView.Adapter<recyclerview.viewholder> {
public static enum ITEM_TYPE {
ITEM_TYPE_IMAGE,
ITEM_TYPE_TEXT
}
private final LayoutInflater mLayoutInflater;
private final Context mContext;
private ArrayList<String> mTitles;
public MultipleItemAdapter(Context context) {
mContext = context;
mLayoutInflater = LayoutInflater.from(context);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ITEM_TYPE.ITEM_TYPE_IMAGE.ordinal()) {
return new ImageViewHolder(mLayoutInflater.inflate(R.layout.item_image, parent, false));
} else {
return new TextViewHolder(mLayoutInflater.inflate(R.layout.item_text, parent, false));
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof TextViewHolder) {
((TextViewHolder) holder).mTextView.setText(mTitles[position]);
} else if (holder instanceof ImageViewHolder) {
((ImageViewHolder) holder).mTextView.setText(mTitles[position]);
}
}
@Override
public int getItemViewType(int position) {
return position % 2 == 0 ? ITEM_TYPE.ITEM_TYPE_IMAGE.ordinal() : ITEM_TYPE.ITEM_TYPE_TEXT.ordinal();
}
@Override
public int getItemCount() {
return mTitles == null ? 0 : mTitles.length;
}
public void addAll(ArrayList<String> list){
if(mTitles!=null){
mTitles.clear();
}else {
mTitles = new ArrayList<>();
}
mTitles.addAll(list);
}
public static class TextViewHolder extends RecyclerView.ViewHolder {
@InjectView(R.id.text_view)
TextView mTextView;
TextViewHolder(View view) {
super(view);
ButterKnife.inject(this, view);
}
}
public static class ImageViewHolder extends RecyclerView.ViewHolder {
@InjectView(R.id.text_view)
TextView mTextView;
@InjectView(R.id.image_view)
ImageView mImageView;
ImageViewHolder(View view) {
super(view);
ButterKnife.inject(this, view);
}
}
}
```
### 其他介绍
#### 01.关于博客汇总链接
- 1.[技术博客汇总](https://www.jianshu.com/p/614cb839182c)
- 2.[开源项目汇总](https://blog.csdn.net/m0_37700275/article/details/80863574)
- 3.[生活博客汇总](https://blog.csdn.net/m0_37700275/article/details/79832978)
- 4.[喜马拉雅音频汇总](https://www.jianshu.com/p/f665de16d1eb)
- 5.[其他汇总](https://www.jianshu.com/p/53017c3fc75d)
#### 02.关于我的博客
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yczbj/activities
- 简书:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
- 开源中国:https://my.oschina.net/zbj1618/blog
- 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 邮箱:[email protected]
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
- 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e
217 changes: 217 additions & 0 deletions ReadMeWiki/02.Adapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
#### 目录介绍
- 01.RecyclerView.Adapter扮演的角色
- 02.重写的方法
- 03.notifyDataSetChanged()刷新数据
- 04.数据变更通知之观察者模式
* a.首先看.notifyDataSetChanged()源码
* b.接着查看.notifyChanged()源码
* c.接着查看setAdapter()源码中的setAdapterInternal(adapter, false, true)方法
* d.notify……方法被调用,刷新数据
- 05.onViewDetachedFromWindow


### 好消息
- 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计N篇[近100万字,陆续搬到网上],转载请注明出处,谢谢!
- **链接地址:https://github.com/yangchong211/YCBlogs**
- 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!




### 01.RecyclerView.Adapter扮演的角色
- 一是,根据不同ViewType创建与之相应的的Item-Layout
- 二是,访问数据集合并将数据绑定到正确的View上




### 02.重写的方法
- 一般常用的重写方法有以下这么几个:
```
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参数)是哪种类型的布局
```
### 03.notifyDataSetChanged()刷新数据
- 当时据集合发生改变时,我们通过调用.notifyDataSetChanged(),来刷新列表,因为这样做会触发列表的重绘,所以并不会出现任何动画效果,因此需要调用一些以notifyItem*()作为前缀的特殊方法,比如:[博客](https://github.com/yangchong211/YCBlogs)
* public final void notifyItemInserted(int position) 向指定位置插入Item
* public final void notifyItemRemoved(int position) 移除指定位置Item
* public final void notifyItemChanged(int position) 更新指定位置Item
### 04.数据变更通知之观察者模式
- a.首先看.notifyDataSetChanged()源码
```
/** @see #notifyItemChanged(int)
* @see #notifyItemInserted(int)
* @see #notifyItemRemoved(int)
* @see #notifyItemRangeChanged(int, int)
* @see #notifyItemRangeInserted(int, int)
* @see #notifyItemRangeRemoved(int, int)
*/
public final void notifyDataSetChanged() {
mObservable.notifyChanged();
}
```
- b.接着查看.notifyChanged();源码
* 被观察者AdapterDataObservable,内部持有观察者AdapterDataObserver集合
```
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);
}
}
}
```
* 观察者AdapterDataObserver,具体实现为RecyclerViewDataObserver,当数据源发生变更时,及时响应界面变化
```
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);
}
}
```
- c.接着查看setAdapter()源码中的setAdapterInternal(adapter, false, true)方法
* setAdapter源码[博客](https://github.com/yangchong211/YCBlogs)
```
public void setAdapter(Adapter adapter) {
// bail out if layout is frozen
setLayoutFrozen(false);
setAdapterInternal(adapter, false, true);
requestLayout();
}
```
* setAdapterInternal(adapter, false, true)源码
```
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();
}
```
- d.notify……方法被调用,刷新数据
* 当数据变更时,调用notify**方法时,Adapter内部的被观察者会遍历通知已经注册的观察者的对应方法,这时界面就会响应变更。[博客](https://github.com/yangchong211/YCBlogs)
### 05.onViewDetachedFromWindow
- 先来看一下源码
```
/**
* Called when a view created by this adapter has been detached from its window.
*
* <p>Becoming detached from the window is not necessarily a permanent condition;
* the consumer of an Adapter's views may choose to cache views offscreen while they
* are not visible, attaching an detaching them as appropriate.</p>
*
* @param holder Holder of the view being detached
*/
public void onViewDetachedFromWindow(VH holder) {
}
```
- 该方法何时调用
- 当适配器创建的view(即列表项view)被窗口分离(即滑动离开了当前窗口界面)就会被调用
- 有何作用
- 这个方法就是用来当你的列表项滑出可见窗口之外的时候,需要重写此方法进行相应的一些操作。
- 这个方法具体什么时候用呢?比如:我有一个列表,列表的每一个列表项里面都要播放一个短视频,这时候,当我滑动一个列表项直至它消失在可视界面时,便会调用onViewDetachedFromWindow()方法,重要的一点,视频控件也会执行它自己的onViewDetachedFromWindow()方法,那么此时我再滑动回来,让该列表项出现在当前界面,会发现视频那一部分就是黑屏或者白屏了。注意,出现这个Bug的条件是,该列表项滑动出可视界面,但是滑动距离不长,因为长的话,你再滑回来就会复用View执行onBindViewHolder()方法。解决方法就是在RecyclerView中重写onViewDetachedFromWindow()方法,对视频进行一个相应的操作(初始化等等)。
### 其他介绍
#### 01.关于博客汇总链接
- 1.[技术博客汇总](https://www.jianshu.com/p/614cb839182c)
- 2.[开源项目汇总](https://blog.csdn.net/m0_37700275/article/details/80863574)
- 3.[生活博客汇总](https://blog.csdn.net/m0_37700275/article/details/79832978)
- 4.[喜马拉雅音频汇总](https://www.jianshu.com/p/f665de16d1eb)
- 5.[其他汇总](https://www.jianshu.com/p/53017c3fc75d)
#### 02.关于我的博客
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yczbj/activities
- 简书:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
- 开源中国:https://my.oschina.net/zbj1618/blog
- 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 邮箱:[email protected]
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
- 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e
Loading

0 comments on commit 6dc60bb

Please sign in to comment.