RecyclerView似乎很慢-解决方法?

时间:2019-01-20 15:21:41

标签: java android android-recyclerview

我正在开发一个跟踪卡路里的应用程序。我有一个用Room实现的SQLite数据库,在我的片段中有一个RecyclerView,它显示了用户保存的食物。

我对列表的性能有疑问。在仿真器中,大约有50个条目需要至少一秒钟的时间。在我的手机(三星Galaxy S5)上,它已经花费了几秒钟。列表元素显示的信息不多,所以我想知道速度。

我已经在Internet上阅读了很多条目,但是还没有变得更聪明。我使用Glide加载图片,否则仅显示2个TextView。

我还想知道问题是否出在notifyDataSetChanged()上。另一种选择是DiffUtil。我已经实现了AsyncListDiffer,但是RecyclerView仍然很慢。

这是我的片段的重要部分:

if(!mAdapter.hasObservers()) mAdapter.setHasStableIds(true);

mAdapter.setOnItemClickListener(new FoodRecyclerViewAdapter.OnItemClickListener() {
@Override
    public void onItemClick(Food food) {
        DiaryEntriesAddDialog dialog = DiaryEntriesAddDialog.newInstance(food);
        dialog.show(getActivity().getSupportFragmentManager(), DiaryEntriesAddDialog.class.getName());
    }
});
mRecyclerViewFood.setAdapter(mAdapter);
mRecyclerViewFood.setLayoutManager(new LinearLayoutManager(getContext());
mRecyclerViewFood.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));

mFoodViewModel = ViewModelProviders.of(this).get(FoodViewModel.class);
mFoodViewModel.getAll().observe(this, new Observer<List<Food>>() {
@Override
    public void onChanged(@Nullable final List<Food> foods) {
        mFoods = foods;
        mAdapter.setItems(foods);
});

我更新列表的功能:

public void setItems(List<Food> foods) {
    mFoods = foods;
    notifyDataSetChanged();
}

这是我的适配器中的ViewHolder:

public class ViewHolder extends RecyclerView.ViewHolder {

    @BindView(R.id.recyclerview_foodlist_item_constraintlayout) ConstraintLayout mConstraintLayout;
    @BindView(R.id.recyclerview_foodlist_item_name) TextView mTextViewName;
    @BindView(R.id.recyclerview_foodlist_item_unit) TextView mTextViewUnit;
    @BindView(R.id.recyclerview_foodlist_item_imageview_type) ImageView mImageViewType;

    @BindArray(R.array.array_dialog_foodadd_units) String[] mUnitNames;

    public ViewHolder(@NonNull View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }

    public void bind(final int position) {
        final Food food = getItem(position);

        mTextViewName.setText(food.getName());
        mTextViewUnit.setText(mUnitNames[food.getUnit()]);
        Glide.with(mContext).load(getEntryTypeDrawableResource(food)).into(mImageViewType);
}

有人有解释吗?我从根本上做错了吗?

编辑 我做了一些进一步的调查。根据事件探查器Profiler Snippet的说法,LinearLayoutManager.layoutChunk是加载/显示项目时最耗时的操作(调试时:〜2秒)。每个onCreateViewHolder()需要3毫秒至100毫秒。然后,将近100个项目可以轻松生成这2秒。 但是为什么那么长?

这是我的onCreateViewHolder()

public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    mContext = viewGroup.getContext();
    mLayoutInflater = LayoutInflater.from(mContext);

    View view = mLayoutInflater.inflate(R.layout.recyclerview_foodlist_item, viewGroup, false);
    return new ViewHolder(view);
} 

这是我要夸大的布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android = "http://schemas.android.com/apk/res/android"
xmlns:app = "http://schemas.android.com/apk/res-auto"
android:id = "@+id/recyclerview_foodlist_item_constraintlayout"
android:layout_width = "match_parent"
android:layout_height = "56dp"
android:background = "?android:attr/selectableItemBackground"
android:clickable = "true"
android:focusable = "true"
android:foreground = "?android:attr/selectableItemBackground"
>

<ImageView
    android:id = "@+id/recyclerview_foodlist_item_imageview_type"
    android:layout_width = "24dp"
    android:layout_height = "24dp"
    android:layout_marginStart = "16dp"
    android:layout_marginTop = "16dp"
    android:layout_marginBottom = "16dp"
    app:layout_constraintBottom_toBottomOf = "parent"
    app:layout_constraintStart_toStartOf = "parent"
    app:layout_constraintTop_toTopOf = "parent"
    />

<TextView
    android:id="@+id/recyclerview_foodlist_item_name"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginTop = "16dp"
    android:layout_marginEnd = "16dp"
    android:layout_marginBottom = "16dp"
    android:text="Name"
    android:textAppearance = "@style/TextAppearance.AppCompat.Menu"
    app:layout_constraintBottom_toBottomOf = "parent"
    app:layout_constraintEnd_toStartOf = "@+id/recyclerview_foodlist_item_unit"
    app:layout_constraintStart_toEndOf = "@+id/recyclerview_foodlist_item_imageview_type"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/recyclerview_foodlist_item_unit"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginTop = "16dp"
    android:layout_marginEnd = "16dp"
    android:layout_marginBottom = "16dp"
    android:text="Unit"
    android:textAppearance = "@style/TextAppearance.AppCompat.Small"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf = "parent"
    />

</android.support.constraint.ConstraintLayout>

0 个答案:

没有答案