美文网首页GitHub上有趣的资源android收集Android开发经验谈
recyclerview万能适配器用法以及源码分析

recyclerview万能适配器用法以及源码分析

作者: 上官若枫 | 来源:发表于2017-10-10 20:35 被阅读165次

源代码引用地址:https://github.com/yiyibb/Zhihu

此篇博客主要是使用鸿洋大神的万能适配器来构造recyclerview,简化了很多代码,但是感觉鸿洋大大的博客文章写的使用方法不够详细,加上后期他又优化了很多代码,这里我详细写明一篇,希望能帮助到大家。

首先在app的gradle文件中加上引用

compile 'com.android.support:recyclerview-v7:25.3.1'//recyclerview
compile 'com.zhy:base-rvadapter:3.0.3'//鸿洋万能的适配器

效果图

Paste_Image.png

接下来看一下项目结构

Paste_Image.png

可以看出这是个DrawerLayout,左边的抽屉栏可以用listview实现或者recyclerview,这里采用recyclerview。我把源代码中的一些重要部分代码摘出来了。做出了这个效果。
可以大概分析一下,这个recyclerview有三个不同的item:header,home,content。来看代码
mainActivity

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);

        mMainMenuList = new ArrayList<>();
        mMainMenuList.add(new DrawerHeaderItem());
        mMainMenuList.add(new DrawerHomeItem());
        addlist();
        mMenuAdapter = new HYDrawerMenuAdapter(this, mMainMenuList);
        rc.setLayoutManager(layoutManager);
        rc.setAdapter(mMenuAdapter);
        mMenuAdapter.setOnItemClickListener(this);//监听接口回调
    }
    public void addlist(){
        for(int i = 0;i < 10;i++){
            ThemesEntity.OthersEntity other = new ThemesEntity.OthersEntity();
            other.setName("心理学");
            mMainMenuList.add(other);
        }
    }
   @Override
    public void onDrawerHeaderItemClick() {
       Toast.makeText(this, "点击登录事件", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onItemViewClick(View view, RecyclerView.ViewHolder holder, int position) {
        Toast.makeText(this, "点击切换界面", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onFollowIVClick(View view, RecyclerView.ViewHolder holder, int position, int offset) {

    }

抛去杂质看本质,最重要的是给HYDrawerMenuAdapter传入了一个list,这个list里包含了所有item,总共三个类,一个DrawerHeaderItem,一个DrawerHomeItem,还有就是十个 ThemesEntity.OthersEntity。
接下来看适配器代码,这里的适配器继承了鸿洋的MultiItemTypeAdapter

public class HYDrawerMenuAdapter extends MultiItemTypeAdapter<DisplaybleItem> {

    private int mSelection = 1;

    private onItemClickListener mOnItemClickListener;

    public HYDrawerMenuAdapter(Context context, List<DisplaybleItem> datas) {
        super(context, datas);
        //加入样本item
        addItemViewDelegate(new DrawerHeaderItemDelegate());
        addItemViewDelegate(new DrawerHomeItemDelegate());
        addItemViewDelegate(new DrawerContentItemDelegate());
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        super.onBindViewHolder(holder, position);

        if (mSelection == position) {
            holder.getConvertView().setBackgroundColor(ContextCompat.getColor(mContext, R.color.colorLightGray));
        } else if (position > 0){
            holder.getConvertView().setBackgroundColor(ContextCompat.getColor(mContext, R.color.colorWhite));
        }
    }

    @Override
    protected void setListener(ViewGroup parent, final ViewHolder viewHolder, int viewType) {

        switch (viewType) {
            case 0:
               // ImageView userIcon = (ImageView) viewHolder.getView(R.id.user_icon);
                TextView loginTV = (TextView)viewHolder.getView(R.id.login);
                Button favoritesBtn = (Button)viewHolder.getView(R.id.action_favorites);
                Button downloadBtn = (Button)viewHolder.getView(R.id.action_download);

               // userIcon.setOnClickListener(handler);
                loginTV.setOnClickListener(handler);//绑定监听事件
                favoritesBtn.setOnClickListener(handler);
                downloadBtn.setOnClickListener(handler);

                break;

            case 1:
            case 2:
                final int offset = 2;

                viewHolder.getConvertView().setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (mOnItemClickListener != null) {
                            int position = viewHolder.getAdapterPosition();
                            mOnItemClickListener.onItemViewClick(v, viewHolder, position);
                        }
                    }
                });

                if (viewType == 2) {
                    viewHolder.getView(R.id.follow_iv).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            if (mOnItemClickListener != null) {
                                int position = viewHolder.getAdapterPosition();
                                mOnItemClickListener.onFollowIVClick(view, viewHolder, position, offset);
                            }
                        }
                    });
                }

                break;
        }

    }

    private View.OnClickListener handler = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (mOnItemClickListener != null) {
                mOnItemClickListener.onDrawerHeaderItemClick();
            }
        }
    };

    public void setSelection(int selection) {
        mSelection = selection;
    }

    public interface onItemClickListener {
        void onDrawerHeaderItemClick();

        void onItemViewClick(View view, RecyclerView.ViewHolder holder, int position);

        void onFollowIVClick(View view, RecyclerView.ViewHolder holder, int position, int offset);
    }

    public void setOnItemClickListener(onItemClickListener onItemClickListener) {
        mOnItemClickListener = onItemClickListener;
    }
}

代码有点长,但是关键部分不多,注意看构造方法,这里面虽然就区区几行,但是引入了鸿洋的大量代码。super关键字表示继承了MultiItemTypeAdapter构造方法里的所有函数体。最关键的是要弄明白刚刚传入的list到底有啥用,而这个addItemViewDelegate方法加入了样本item又是干啥的,快捷键进入源码分析。

Paste_Image.png

发现这个list集合主要用于确认item的类别,进而点击getItemViewType方法。

Paste_Image.png

这里又出现一个delegates。联系上下文,可以看出来刚刚addItemViewDelegate方法加入的对象就是放到了delegates这个集合中,也就是说这个集合承载这所有的item类型,也就是那三种类型。进而将这个集合遍历,对照传入的所有item看符合哪个类型并返回一定的参数。

Paste_Image.png

画个草图可能更清楚一些。

再从整体来分析一下,要使用这个适配器来展示三种item,就需要传入两个集合一个是所有的item集合,另外就是这三个item样式的集合。

明白了整体流程以后我们来看一下细节,这个是十个“心理学”的item样式,其他的跟这个差不多,具体项目包看后文链接。

public class DrawerContentItemDelegate implements ItemViewDelegate<DisplaybleItem>{

    @Override
    public int getItemViewLayoutId() {
        return R.layout.item_drawer_menu_content;//用于传入布局文件名
    }

    @Override
    public boolean isForViewType(DisplaybleItem item, int position) {
        return item instanceof ThemesEntity.OthersEntity;//用于对比item是否属于这个类型
    }

    @Override
    public void convert(ViewHolder holder, DisplaybleItem displaybleItem, final int position) {
//用于改变item上的文字
        holder.setText(R.id.item_theme_list_tv, ((ThemesEntity.OthersEntity)displaybleItem).getName());
    }

}

适配器还有监听事件,采用的是接口回调,具体看HYDrawerMenuAdapter中的setListener方法,这里需要注意的是setListener方法并没有使用super。监听的接口回调很简单,不再赘述。

项目地址:http://download.csdn.net/download/qq_32331397/10014715

感兴趣的可以关注我最新开的公众号,重在分享!!微信搜索 开发Android的小学生

qrcode_for_gh_c686d73be7e1_430.jpg

相关文章

网友评论

    本文标题:recyclerview万能适配器用法以及源码分析

    本文链接:https://www.haomeiwen.com/subject/bukvyxtx.html