android recyclerView adapter 的 itemType的使用

  • RecyclerView出来已经很久了。我对于之的使用,也仅限于当成ListVieworGridView的使用。最近项目中有一个需求刚好需要用到多种item的展示。
  • 我之前使用RecyclerViewadapter 全部使用的是hongyang/base-adapter。非常的方便。而且也提供多种item的展示的功能。但是………我并没有找到正确的使用方式。于是这回就用到了原生的RecyclerView.Adapter来实现多种itemType


  • 我的项目中,用到的是两种item。为了以后查找方便,就记录在这里了。

public class LockAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<LockInfo> dataList;
    private final Context mContext;
    private boolean canClick;
    private int lockCount;
    private int unLockCount;
    private int mUnLockCountPos;
    private int mLockCountPos;

    public void setCanClick(boolean canClick) {
        this.canClick = canClick;
        notifyDataSetChanged();
    }


    public int getUnLockCountPos() {
        return mUnLockCountPos;
    }

    public int getLockCount() {
        return lockCount;
    }

    public int getUnLockCount() {
        return unLockCount;
    }

    public LockAdapter(@NonNull Context context, @NonNull List<LockInfo> dataList) {
        this.mContext = context;
        this.dataList = dataList;
        lockCount = Observable.fromIterable(dataList).filter(it -> it.locked)
                .toList().blockingGet().size() - 1;
        unLockCount = dataList.size() - 1 - (lockCount + 1);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == 0) {
            // default item
            View view = LayoutInflater.from(mContext)
                    .inflate(R.layout.item_app_list_layout, parent, false);

            return new NormalVH(view);

        } else if (viewType == 1) {
            // first item
            View view = LayoutInflater.from(mContext)
                    .inflate(R.layout.item_app_list_first_layout, parent, false);
            return new FirstVH(view);
        } else {
            return null;
        }
    }


    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
        int adapterPosition = viewHolder.getAdapterPosition();
        LockInfo info = dataList.get(adapterPosition);
        if (viewHolder instanceof NormalVH) {
            NormalVH holder = (NormalVH) viewHolder;
            holder.ivIcon.setImageDrawable(info.appIcon);
            holder.cbChecked.setChecked(info.locked);
            holder.cbChecked.setEnabled(canClick);
            holder.itemView.setEnabled(canClick);
            holder.tvPackageName.setText(info.packageName);
            if (canClick) {
                holder.itemView.setOnClickListener(v -> {
                    info.locked = !info.locked;
                    if (info.locked) {
                        lockCount += 1;
                        unLockCount -= 1;
                    } else {
                        lockCount -= 1;
                        unLockCount += 1;
                    }
                    notifyItemChanged(adapterPosition);
                    notifyItemChanged(mLockCountPos);
                    notifyItemChanged(mUnLockCountPos);
                    EventBus.getDefault().post(new ChangeEvent(lockCount, unLockCount));
                });
            }
        } else if (viewHolder instanceof FirstVH) {
            FirstVH holder = (FirstVH) viewHolder;
            if (info.locked) {
                this.mLockCountPos = adapterPosition;
                holder.tvFirst.setText(mContext.getString(R.string.has_locked_count, lockCount));
            } else {
                this.mUnLockCountPos = adapterPosition;
                holder.tvFirst.setText(mContext.getString(R.string.un_locked_count, unLockCount));
            }
        }
    }

    @Override
    public int getItemCount() {
        return dataList.size();
    }

    private static class NormalVH extends RecyclerView.ViewHolder {

        private final View itemView;
        private final ImageView ivIcon;

        private final TextView tvPackageName;
        private final CheckBox cbChecked;

        NormalVH(View itemView) {
            super(itemView);
            this.itemView = itemView;
            ivIcon = (ImageView) itemView.findViewById(R.id.item_app_list_iv);
            tvPackageName = (TextView) itemView.findViewById(R.id.item_app_list_tv_name);
            cbChecked = (CheckBox) itemView.findViewById(R.id.item_app_list_cb);
        }
    }

    private static class FirstVH extends RecyclerView.ViewHolder {

        private final TextView tvFirst;

        FirstVH(View itemView) {
            super(itemView);
            tvFirst = (TextView) itemView.findViewById(R.id.item_app_list_first_tv);
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (dataList.get(position).first) {
            return 1;
        } else {
            return super.getItemViewType(position);
        }
    }

    public void updateData(@NonNull List<LockInfo> update) {
        this.dataList = update;
        notifyDataSetChanged();
    }
}
  • 其实也是看到这篇文字之后,才知道怎么弄的。
  • 强调一下,多个itemType时,需要注意的地方:

    • Adapter需要直接继承RecyclerView.Adapter<RecyclerView.ViewHolder>,并且不要改变泛型类。
    • 重写int getItemViewType(int position)方法,第一种item默认返回super.getItemViewType(position);,也就是0,第二种item再返回一个不同的值,我这里给的是1.(第三种,也是一样,我这里没有实现)
    • 有几种item就写几个RecyclerView.ViewHolder,我这里是两个,于是我写了两个,分别是private static class NormalVH extends RecyclerView.ViewHolder{...}private static class FirstVH extends RecyclerView.ViewHolder {...}这两个。
    • onCreateViewHolder()方法中,分别判断当前用的是哪一种ViewHolder,比如我这里:
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == 0) {
            // default item
            View view = LayoutInflater.from(mContext)
                    .inflate(R.layout.item_app_list_layout, parent, false);
    
            return new NormalVH(view);
    
        } else if (viewType == 1) {
            // first item
            View view = LayoutInflater.from(mContext)
                    .inflate(R.layout.item_app_list_first_layout, parent, false);
            return new FirstVH(view);
        } else {
            return null;
        }
    }
    • onBindViewHolder()方法中,也是一样,要根据不同的ViewHolder做不同的绑定view的操作。比如我这里:
      @Override
      public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
          int adapterPosition = viewHolder.getAdapterPosition();
          LockInfo info = dataList.get(adapterPosition);
          if (viewHolder instanceof NormalVH) {
              NormalVH holder = (NormalVH) viewHolder;
              holder.ivIcon.setImageDrawable(info.appIcon);
              holder.cbChecked.setChecked(info.locked);
              holder.cbChecked.setEnabled(canClick);
              holder.itemView.setEnabled(canClick);
              holder.tvPackageName.setText(info.packageName);
              if (canClick) {
                  holder.itemView.setOnClickListener(v -> {
                      info.locked = !info.locked;
                      if (info.locked) {
                          lockCount += 1;
                          unLockCount -= 1;
                      } else {
                          lockCount -= 1;
                          unLockCount += 1;
                      }
                      notifyItemChanged(adapterPosition);
                      notifyItemChanged(mLockCountPos);
                      notifyItemChanged(mUnLockCountPos);
                      EventBus.getDefault().post(new ChangeEvent(lockCount, unLockCount));
                  });
              }
          } else if (viewHolder instanceof FirstVH) {
              FirstVH holder = (FirstVH) viewHolder;
              if (info.locked) {
                  this.mLockCountPos = adapterPosition;
                  holder.tvFirst.setText(mContext.getString(R.string.has_locked_count, lockCount));
              } else {
                  this.mUnLockCountPos = adapterPosition;
                  holder.tvFirst.setText(mContext.getString(R.string.un_locked_count, unLockCount));
              }
          }
      }
  • 主要的需要注意的地方就是这几点了。
  • 另外,这个代码如果直接拷过去是一定没有办法运行的。主要是讲一下实现过程。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Android中,RecyclerView是一个强大的UI组件,用于显示大量数据列表。当我们需要显示大量数据时,通常会需要进行分页加载,实现上拉加载更多的功能。 下面是实现RecyclerView上拉加载更多的一般步骤: 1. 在RecyclerViewAdapter中添加一个Footer View,用于显示“正在加载中”或“没有更多数据”等提示信息。 2. 监听RecyclerView的滚动事件,当滚动到底部时,显示Footer View,并开始加载更多数据。 3. 加载更多数据时,更新RecyclerView的数据源并刷新Adapter。同时,隐藏Footer View。 下面是一个简单的实现代码: 1. 添加Footer View ```java public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private static final int TYPE_ITEM = 0; private static final int TYPE_FOOTER = 1; private boolean mShowFooter = true; // 是否显示Footer,默认显示 // ... // 在创建ViewHolder时,判断是否为Footer View @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == TYPE_FOOTER) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.footer_view, parent, false); return new FooterViewHolder(view); } // ... } // 在绑定ViewHolder时,根据位置判断是否为Footer View @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof FooterViewHolder) { FooterViewHolder footerHolder = (FooterViewHolder) holder; if (mShowFooter) { footerHolder.mFooterView.setVisibility(View.VISIBLE); } else { footerHolder.mFooterView.setVisibility(View.GONE); } } else { // ... } } // 返回ItemType @Override public int getItemViewType(int position) { if (!mShowFooter) { return TYPE_ITEM; } if (position == getItemCount() - 1) { return TYPE_FOOTER; } return TYPE_ITEM; } // 显示或隐藏Footer View public void showFooter(boolean show) { mShowFooter = show; notifyDataSetChanged(); } // Footer ViewHolder public static class FooterViewHolder extends RecyclerView.ViewHolder { public View mFooterView; public FooterViewHolder(View itemView) { super(itemView); mFooterView = itemView; } } } ``` 2. 监听RecyclerView滚动事件 ```java mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { // 是否正在向上滑动 private boolean isSlidingUpward = false; @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == RecyclerView.SCROLL_STATE_IDLE) { // 当滚动停止时 LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); // 最后一个完全可见的item的位置 int lastVisibleItem = layoutManager.findLastCompletelyVisibleItemPosition(); int totalItemCount = layoutManager.getItemCount(); // 判断是否滚动到底部,并且不是正在向上滑动 if (lastVisibleItem == (totalItemCount - 1) && isSlidingUpward) { // 加载更多数据 // ... } } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); // 判断是否正在向上滑动 isSlidingUpward = dy > 0; } }); ``` 3. 加载更多数据 ```java private int currentPage = 1; private boolean isLoading = false; private void loadMoreData() { if (isLoading) { return; } isLoading = true; // 显示Footer View mAdapter.showFooter(true); // 加载数据 // ... // 更新数据源 // ... // 刷新Adapter mAdapter.notifyDataSetChanged(); // 隐藏Footer View mAdapter.showFooter(false); isLoading = false; currentPage++; } ``` 以上是RecyclerView上拉加载更多的一般实现步骤,具体实现可能会因为业务需求有所不同,但是以上步骤可以为你提供一个基本的思路。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值