我正在开发一个跟踪卡路里的应用程序。我有一个用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);
}
有人有解释吗?我从根本上做错了吗?
编辑
我做了一些进一步的调查。根据事件探查器的说法,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>