android - Android Expandable-Header RecyclerView 滚动滞后
问题描述
我的 Expandable 出现滚动延迟问题RecyclerView
。应该注意的是,滚动浏览标题时会发生延迟,而不是滚动浏览子项时。
行布局(recycler_row_expandable.xml
):
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/blonde">
<ImageView
android:id="@+id/categoryPicture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/headerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="23sp"
android:textStyle="bold"
android:textColor="@color/black"
android:layout_marginStart="5dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/categoryPicture"
app:layout_constraintTop_toTopOf="parent"
/>
<ImageView
android:id="@+id/headerPicture"
android:src="@drawable/logo_arrow_expandable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/margin_standard"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</android.support.constraint.ConstraintLayout>
适配器:
public class ActivityRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements
ActivityRecyclerHeaderViewHolder.HeaderViewHolderCallback, ActivityRecyclerChildViewHolder.ChildViewHolderCallback {
private Context context;
private final int ACTIVITY_TYPE = 1;
private final int HEADER_TYPE = 2;
private List<String> activityHeaderList;
private List<String> activityChildList;
private Map<String, Integer> numberOfChildrenPerParentNameMap;
private SparseArray<ActivityRecyclerViewType> viewTypes;
private SparseIntArray headerExpandTracker;
public ActivityRecyclerAdapter(Context context, List<String> activityHeaderList, List<String> activityTypeList, Map<String, Integer> numberOfChildrenPerParent) {
this.context = context;
this.activityHeaderList = activityHeaderList;
this.activityChildList = activityTypeList;
this.numberOfChildrenPerParentNameMap = numberOfChildrenPerParent;
headerExpandTracker = new SparseIntArray(activityHeaderList.size());
viewTypes = new SparseArray<>(activityHeaderList.size() + activityTypeList.size());
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case ACTIVITY_TYPE:
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_row_child, parent, false);
return new ActivityRecyclerChildViewHolder(view, this);
case HEADER_TYPE:
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_row_expandable, parent, false);
return new ActivityRecyclerHeaderViewHolder(view, this);
default:
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_row_child, parent, false);
return new ActivityRecyclerChildViewHolder(view, this);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int itemViewType = getItemViewType(position);
ActivityRecyclerViewType viewType = viewTypes.get(position);
if (itemViewType == ACTIVITY_TYPE) {
bindChildViewHolder(holder, viewType);
} else {
bindHeaderViewHolder(holder, position, viewType);
}
}
private void bindHeaderViewHolder(RecyclerView.ViewHolder holder, int position, ActivityRecyclerViewType viewType) {
int dataIndex = viewType.getDataIndex();
ActivityRecyclerHeaderViewHolder headerViewHolder = (ActivityRecyclerHeaderViewHolder) holder;
headerViewHolder.sectionTitle.setText(activityHeaderList.get(dataIndex));
if (position < ChooseCategoryActivity.allImagesNames.length) {
headerViewHolder.categoryImage.setImageDrawable(context.getResources().getDrawable(ChooseCategoryActivity.allImagesNames[position]));
}
if (isExpanded(position)) {
headerViewHolder.sectionTitle
.setCompoundDrawablesWithIntrinsicBounds(null, null, null/*headerViewHolder.arrowUp*/, null);
} else {
headerViewHolder.sectionTitle
.setCompoundDrawablesWithIntrinsicBounds(null, null, null /*headerViewHolder.arrowDown*/, null);
}
}
private void bindChildViewHolder(RecyclerView.ViewHolder holder, ActivityRecyclerViewType viewType) {
int dataIndex = viewType.getDataIndex();
((ActivityRecyclerChildViewHolder) holder).name.setText(activityChildList.get(dataIndex));
}
@Override
public int getItemCount() {
int count = 0;
if (activityChildList != null && activityHeaderList != null && headerExpandTracker != null) {
viewTypes.clear();
int collapsedCount = 0;
for (int i = 0; i < activityHeaderList.size(); i++) {
viewTypes.put(count, new ActivityRecyclerViewType(i, HEADER_TYPE));
count += 1;
String userType = activityHeaderList.get(i);
int childCount = numberOfChildrenPerParentNameMap.get(userType);
if (headerExpandTracker.get(i) != 0) {
// Expanded State
for (int j = 0; j < childCount; j++) {
viewTypes.put(count, new ActivityRecyclerViewType(count - (i + 1) + collapsedCount, ACTIVITY_TYPE));
count += 1;
}
} else {
// Collapsed
collapsedCount += childCount;
}
}
}
return count;
}
@Override
public int getItemViewType(int position) {
if (viewTypes.get(position).getType() == HEADER_TYPE) {
return HEADER_TYPE;
} else {
return ACTIVITY_TYPE;
}
}
@Override
public void onHeaderClick(int position) {
ActivityRecyclerViewType viewType = viewTypes.get(position);
int dataIndex = viewType.getDataIndex();
String userType = activityHeaderList.get(dataIndex);
int childCount = numberOfChildrenPerParentNameMap.get(userType);
if (headerExpandTracker.get(dataIndex) == 0) {
// Collapsed. Now expand it
headerExpandTracker.put(dataIndex, 1);
notifyItemRangeInserted(position + 1, childCount);
ChooseCategoryActivity.HEADER_EXPANDED_NUMBER = position;
} else {
// Expanded. Now collapse it
headerExpandTracker.put(dataIndex, 0);
notifyItemRangeRemoved(position + 1, childCount);
ChooseCategoryActivity.HEADER_EXPANDED_NUMBER = -1;
}
}
@Override
public boolean isExpanded(int position) {
int dataIndex = viewTypes.get(position).getDataIndex();
return headerExpandTracker.get(dataIndex) == 1;
}
@Override
public void onChildClick(String name) {
if (context instanceof ChooseCategoryActivity) {
((ChooseCategoryActivity) context).finishChoosingActivity(name);
}
}
}
我试过用recyclerView.setHasFixedSize(true)
,
recyclerView.setItemViewCacheSize(20)
,
recyclerView.setDrawingCacheEnabled(true)
,
recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH)
& adapter.setHasStableIds(true)
对性能没有影响。
如有必要,可以发布其他组件。
解决方案
推荐阅读
- javascript - 当我使用 belongsToMany 关联时,Sequelize 中的自动急切加载
- reactjs - 如何通过地图功能仅打开一个模式
- javascript - Firefox 性能和 React
- google-analytics - 在 Google Analytics 中按前 10 天细分用户
- laravel - laravel 中的 @csrf 是否包含在内?
- php - 带有 apache2 和 php-fpm over Unix 套接字的单个 docker 与带有 TCP/IP 套接字的 2 个不同容器(apache2 和 php-fpm)?
- python - Django 自定义命令在没有调试日志的情况下写入文件
- reactjs - 当依赖项之一发生更改时,您能否使 useEffect 仅运行一次,但如果再次更改则不运行?
- php - Smarty:如果 {Multi Word String} 的开头/结尾有空格,则修剪它/它们
- ajax - 无法从 Web 浏览器以外的 HTTP 客户端访问 URL 内容