【问题标题】:Bad performance when use RecyclerView inside NestedScrollView在 NestedScrollView 中使用 RecyclerView 时性能不佳
【发布时间】:2017-12-18 16:59:44
【问题描述】:

我正在开发搜索联系人功能,在该屏幕中,NestedScrollView 内有一个 RecyclerViewfillViewport = true)。 屏幕设计:此设计已被客户接受,我无法更改

将当前设备的所有联系人加载到一个ArrayList中后,从这个数组中过滤搜索结果。
有几种情况会使应用程序非常滞后
1. 当用户输入一个没有结果的输入,然后用户清除搜索,我必须再次显示所有结果NestedScrollView 必须为 RecyclerView 的所有项目(例如:300 个项目)呈现 UI。
2. 当结果的数量有很多变化时(例如,从 1 到 300 项)。 NestedScrollView 必须为 RecyclerView 的许多项呈现 UI

我知道这个设计破坏了 RecyclerView 的回收技术,但我无法改变它。
我尝试了什么:

recyclerView.setNestedScrollingEnabled(false);

在 AndroidManifest 中:

android:windowSoftInputMode="adjustNothing"

适配器:

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

    private List<MobileContact> contacts;
    private Context context;

    public RecyclerContactAdapter() {
        contacts = new ArrayList<>();
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        this.context = parent.getContext();
        View view = LayoutInflater.from(context)
                .inflate(R.layout.item_recycler_contact, parent, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        //set data for view
    }

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

    protected class ViewHolder extends RecyclerView.ViewHolder {
        private TextView tvAlphabetHeader;
        private CircleImageView civAvatar;
        private TextView tvContactName;
        private TextView tvStatus;
        private CheckBox cbInvited;
        private RelativeLayout rlAlphabetHeader;
        private RelativeLayout rlContainer;

        protected ViewHolder(View itemView) {
            super(itemView);
            tvAlphabetHeader = itemView.findViewById(R.id.item_recycler_contact_tv_alphabet_header);
            civAvatar = itemView.findViewById(R.id.item_recycler_contact_civ_avatar);
            tvContactName = itemView.findViewById(R.id.item_recycler_contact_tv_name);
            tvStatus = itemView.findViewById(R.id.item_recycler_contact_tv_status);
            cbInvited = itemView.findViewById(R.id.item_recycler_contact_cb_contact);
            rlAlphabetHeader =  itemView.findViewById(R.id.item_recycler_contact_rl_alphabet);
            rlContainer = itemView.findViewById(R.id.item_recycler_contact_rl_contact);
        }
    }

    public void addAll(List<MobileContact> mobileContacts) {
        this.contacts.clear();
        this.contacts.addAll(mobileContacts);
        notifyDataSetChanged();
    }

    public void add(MobileContact mobileContact) {
        this.contacts.add(mobileContact);
    }

    public List<MobileContact> getContacts() {
        return this.contacts;
    }

}

【问题讨论】:

  • 发布您的回收器适配器
  • 您能再解释一下您的 ui 设计吗?其中哪一部分是可滚动的?即你可以滚动nestedscrollview,也可以在nestedscrollview 内滚动recyclerview 还是什么?
  • @Okas 除了工具栏,用户可以滚动整个屏幕
  • @ErginErsoy 好的,我要发了,如果我不使用 NestedScrollView,这个功能可以顺利运行,导致回收技术。
  • 当 RecyclerView 本身已经可以滚动时,为什么还需要 ScrollView?!

标签: android performance android-recyclerview android-nestedscrollview


【解决方案1】:

您错误地使用了 RecyclerView。不要将 RecyclerView 放在 NestedScrollView 中,而是将“标题”和“搜索框”放在 RecyclerView 中作为不同的视图类型。

answer 就是一个很好的例子。

【讨论】:

  • 这个方法听起来很合适,但是会有4种不同的视图类型:标题(TextView),按钮,搜索框,普通项,每个处理所有事件都很复杂。
  • 一开始看起来很复杂。其实这是标准做法。再看看你的用户界面,你似乎可以把你的标题、按钮和搜索框放在一个布局中,所以它只有两种视图类型。
  • 哦,我明白了,我希望我能向您展示确切的屏幕设计。我会试试你的解决方案
  • 如果我在 List 上有一个片段,我无法将片段中的所有逻辑移动到适配器中的标题中怎么办?并且片段不能在适配器内部使用。
  • @David,你可能需要重新设计。
猜你喜欢
  • 1970-01-01
  • 2016-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-22
  • 1970-01-01
相关资源
最近更新 更多