加速查看 inflation
Speed up view inflation
在我的应用程序中,我必须为每一天显示一个带有自定义布局的日历。为此,我将 RecyclerView 与此布局管理器一起使用:new GridLayoutManager(view.getContext(), 7)
和自定义适配器。适配器必须充气 35 到 49 个物品(7 个用于星期几,另外 4 到 6 行,每行 7 个物品用于一个月中的几天)。所有这些都需要 1 秒或更多,这太长了,因为它会使应用程序变得迟钝。我注意到延迟的原因是视图膨胀。膨胀视图需要 15 到 25 毫秒,乘以 +-50 视图,你有整整一秒。这是我在 onCreateViewHolder
中用于膨胀视图的代码,大约需要 20 毫秒:
View view = LayoutInflater.from(viewGroup.getContext()).inflate(this.itemLayout, viewGroup, false);
有什么方法可以加快速度吗?
编辑
Xml:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView_monthEntries"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never"/>
片段:
RecyclerView recyclerViewMonthEntries = (RecyclerView) view.findViewById(R.id.recyclerView_monthEntries);
this.monthEntryAdapter = new CalendarMonthEntryAdapter(view.getContext(), calendar, null, R.layout.listitem_calendar_month_entry, R.layout.listitem_calendar_month_day, recommendedRowHeight);
this.monthEntryAdapter.setListener(this);
recyclerViewMonthEntries.setLayoutManager(new GridLayoutManager(view.getContext(), 7));
recyclerViewMonthEntries.setAdapter(this.monthEntryAdapter);
recyclerViewMonthEntries.setItemAnimator(new DefaultItemAnimator());
OnCreateViewHolder:
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType)
{
switch (viewType)
{
case TYPE_HEADER:
View viewHeader = LayoutInflater.from(viewGroup.getContext()).inflate(this.headerLayout, viewGroup, false);
return new DayOfWeekViewHolder(viewHeader);
case TYPE_ENTRY:
View viewEntry = LayoutInflater.from(viewGroup.getContext()).inflate(this.itemLayout, viewGroup, false);
return new CalendarMonthEntryViewHolder(viewEntry);
default:
return null;
}
}
OnBindViewHolder:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i)
{
switch (this.getItemViewType(i))
{
case TYPE_HEADER:
this.onBindHeaderViewHolder((DayOfWeekViewHolder) viewHolder, i);
break;
case TYPE_ENTRY:
this.onBindEntryViewHolder((CalendarMonthEntryViewHolder) viewHolder, i - 7);
break;
}
}
绑定没什么特别的,只是一些 setText 和 setVisibility。绑定大约需要 1 毫秒。我在inflate之前和之后都放了日志,这就是一直消耗的东西。
我不知道你的代码,但我盲目推荐在线性布局中使用 table 适配器。
但要进一步发展:
你需要做出决定。您是否需要加载后完全可用的自定义视图,或者您可以使用一些基本视图格式(对所有视图都相同)来呈现日历,然后根据需要进行自定义。这是一个设计和用户体验决定。
作为一种方法,您可以,
- 将日历加载为包含 table 适配器的单个视图。
- 点击时加载自定义视图
- 应用程序启动后,用自定义视图填充所有 table 单元格。这就是用户体验设计。您必须决定是否直接加载并在准备好后立即展示它们。或者显示一些自定义 "spinning" 动画。或者将整个加载工作隐藏在动画演示效果中(以动画方式显示日历,这将被视为 UX 增强)。
我最后一件一件地添加了我的物品。我从 1 开始计数,然后在 onBindViewHolder
:
末尾的计数上加 1
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i)
{
//Normal code here
new Handler().post(new Runnable()
{
@Override
public void run()
{
if(currentCount < maxCount)
{
currentCount++;
notifyItemInserted(currentCount - 1);
}
}
});
}
我认为这不是最佳解决方案,但它确实有效。项目一项一项地弹出屏幕。
在我的应用程序中,我必须为每一天显示一个带有自定义布局的日历。为此,我将 RecyclerView 与此布局管理器一起使用:new GridLayoutManager(view.getContext(), 7)
和自定义适配器。适配器必须充气 35 到 49 个物品(7 个用于星期几,另外 4 到 6 行,每行 7 个物品用于一个月中的几天)。所有这些都需要 1 秒或更多,这太长了,因为它会使应用程序变得迟钝。我注意到延迟的原因是视图膨胀。膨胀视图需要 15 到 25 毫秒,乘以 +-50 视图,你有整整一秒。这是我在 onCreateViewHolder
中用于膨胀视图的代码,大约需要 20 毫秒:
View view = LayoutInflater.from(viewGroup.getContext()).inflate(this.itemLayout, viewGroup, false);
有什么方法可以加快速度吗?
编辑
Xml:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView_monthEntries"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never"/>
片段:
RecyclerView recyclerViewMonthEntries = (RecyclerView) view.findViewById(R.id.recyclerView_monthEntries);
this.monthEntryAdapter = new CalendarMonthEntryAdapter(view.getContext(), calendar, null, R.layout.listitem_calendar_month_entry, R.layout.listitem_calendar_month_day, recommendedRowHeight);
this.monthEntryAdapter.setListener(this);
recyclerViewMonthEntries.setLayoutManager(new GridLayoutManager(view.getContext(), 7));
recyclerViewMonthEntries.setAdapter(this.monthEntryAdapter);
recyclerViewMonthEntries.setItemAnimator(new DefaultItemAnimator());
OnCreateViewHolder:
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType)
{
switch (viewType)
{
case TYPE_HEADER:
View viewHeader = LayoutInflater.from(viewGroup.getContext()).inflate(this.headerLayout, viewGroup, false);
return new DayOfWeekViewHolder(viewHeader);
case TYPE_ENTRY:
View viewEntry = LayoutInflater.from(viewGroup.getContext()).inflate(this.itemLayout, viewGroup, false);
return new CalendarMonthEntryViewHolder(viewEntry);
default:
return null;
}
}
OnBindViewHolder:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i)
{
switch (this.getItemViewType(i))
{
case TYPE_HEADER:
this.onBindHeaderViewHolder((DayOfWeekViewHolder) viewHolder, i);
break;
case TYPE_ENTRY:
this.onBindEntryViewHolder((CalendarMonthEntryViewHolder) viewHolder, i - 7);
break;
}
}
绑定没什么特别的,只是一些 setText 和 setVisibility。绑定大约需要 1 毫秒。我在inflate之前和之后都放了日志,这就是一直消耗的东西。
我不知道你的代码,但我盲目推荐在线性布局中使用 table 适配器。
但要进一步发展:
你需要做出决定。您是否需要加载后完全可用的自定义视图,或者您可以使用一些基本视图格式(对所有视图都相同)来呈现日历,然后根据需要进行自定义。这是一个设计和用户体验决定。
作为一种方法,您可以,
- 将日历加载为包含 table 适配器的单个视图。
- 点击时加载自定义视图
- 应用程序启动后,用自定义视图填充所有 table 单元格。这就是用户体验设计。您必须决定是否直接加载并在准备好后立即展示它们。或者显示一些自定义 "spinning" 动画。或者将整个加载工作隐藏在动画演示效果中(以动画方式显示日历,这将被视为 UX 增强)。
我最后一件一件地添加了我的物品。我从 1 开始计数,然后在 onBindViewHolder
:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i)
{
//Normal code here
new Handler().post(new Runnable()
{
@Override
public void run()
{
if(currentCount < maxCount)
{
currentCount++;
notifyItemInserted(currentCount - 1);
}
}
});
}
我认为这不是最佳解决方案,但它确实有效。项目一项一项地弹出屏幕。