在 NestedScrollView 中使用 RecyclerView 时性能不佳
Bad performance when use RecyclerView inside NestedScrollView
我正在开发一个搜索联系人功能,在那个屏幕中,RecyclerView 里面 NestedScrolView ( fillViewport = true)。
画面设计:(此设计已被客户接受,我无法更改)
将当前设备的所有联系人加载到一个ArrayList中后,搜索结果从这个数组中筛选出来。
有几种情况使应用程序非常滞后:
1. 当用户输入没有结果,然后用户清除搜索,我必须显示所有结果 再次。 NestedScrollView 必须为 RecyclerView 的所有项目呈现 UI(例如:300 个项目)。
2. 当结果数量有很多变化时(例如,从 1 条到 300 条)。 NestedScrollView 必须为 RecyclerView [=37] 的很多项呈现 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;
}
}
您没有正确使用 RecyclerView。不要将 RecyclerView 放在 NestedScrollView 中,而是将 "Header" 和 "Search box" 放在 RecyclerView 中作为不同的视图类型。
这个answer就是一个很好的例子。
我正在开发一个搜索联系人功能,在那个屏幕中,RecyclerView 里面 NestedScrolView ( fillViewport = true)。
画面设计:(此设计已被客户接受,我无法更改)
将当前设备的所有联系人加载到一个ArrayList中后,搜索结果从这个数组中筛选出来。
有几种情况使应用程序非常滞后:
1. 当用户输入没有结果,然后用户清除搜索,我必须显示所有结果 再次。 NestedScrollView 必须为 RecyclerView 的所有项目呈现 UI(例如:300 个项目)。
2. 当结果数量有很多变化时(例如,从 1 条到 300 条)。 NestedScrollView 必须为 RecyclerView [=37] 的很多项呈现 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;
}
}
您没有正确使用 RecyclerView。不要将 RecyclerView 放在 NestedScrollView 中,而是将 "Header" 和 "Search box" 放在 RecyclerView 中作为不同的视图类型。
这个answer就是一个很好的例子。