加速查看 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 适配器。

但要进一步发展:

你需要做出决定。您是否需要加载后完全可用的自定义视图,或者您可以使用一些基本视图格式(对所有视图都相同)来呈现日历,然后根据需要进行自定义。这是一个设计和用户体验决定。

作为一种方法,您可以,

  1. 将日历加载为包含 table 适配器的单个视图。
  2. 点击时加载自定义视图
  3. 应用程序启动后,用自定义视图填充所有 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);
            }
        }
    });
}

我认为这不是最佳解决方案,但它确实有效。项目一项一项地弹出屏幕。