如何提高(感知)使用 Android 创建复杂 ListView 的速度?

Posted

技术标签:

【中文标题】如何提高(感知)使用 Android 创建复杂 ListView 的速度?【英文标题】:How can I improve (perceived) speed on a complex ListView creation with Android? 【发布时间】:2010-11-21 20:43:18 【问题描述】:

我有一个使用 ListView 作为主屏幕的应用程序。每行根据数据显示一些文本、一个复选框和图像,由于您无法使用标准的 ListAdapter 做到这一点,所以我制作了自己的。

每次列表数据发生更改(添加/删除行、检查提示、导航等)时,我都会使用此方法刷新列表显示:

public void refreshList()

    // fetch the new items
    ItemDbHelper items = new ItemDbHelper(this);
    Cursor item_cursor = items.fetchItemForCurrentView(this.current_context_filter);

    // do not use "start managing cursor" here or resume() won't work
    // anymore since the cursor will be closed despite we still need it

    // set the welcome message if no items to display
    if (item_cursor.getCount() == 0)
    
        TextView message = (TextView) this.findViewById(R.id.home_message);
        message.setVisibility(View.VISIBLE);
    

    ListView list = this.task_list;
    ItemListAdapter item_cursor_adater = (ItemListAdapter) list.getAdapter();

    // close the old cursor manually and replace it with the new one
    item_cursor_adater.getCursor().close();
    item_cursor_adater.changeCursor(item_cursor);
    // reset some cache data in the adapter
    item_cursor_adater.reset();
    // tell the list to refresh
    item_cursor_adater.notifyDataSetChanged();

    // to easy navigation, we set the focus the last selected item
    // set the last modified item as selected
    int selected_index = this.getItemPositionFromId(list, 
                                                    this.getCurrentContextFilter()
                                                        .getSelectedTaskId());

    list.setSelection(selected_index);

一些事实:

items.fetchItemForCurrentView() 触发非常繁重的 SQL 查询

this.getItemPositionFromId() 在整个 ListView 上逐行循环以查找具有给定 id 的行的索引。

item_cursor_adapter 扩展了 SimpleCursorAdapter 并覆盖了

public View getView(int position, View convertView, ViewGroup parent)

这是一个相当繁重的方法。

此方法在典型应用程序用例中经常根据用户需求调用,等待屏幕刷新会降低用户体验。

您对如何改进有什么建议吗?

一些想法:

使用线程加载数据。但是,之后如何补充列表呢?如何让它在屏幕上看起来不打扰? 重用一些对象/使用一些我没有想到的缓存。 找到一种无需重新加载所有内容即可更新列表的方法 更改光标适配器的实现。也许扩展一个更高效的父级或使用比 getView 更好的东西?

【问题讨论】:

【参考方案1】:

您可以摆脱所有这些代码,只需在Cursor 上调用requery()。顾名思义,它首先重新运行生成Cursor 的查询。这将获取数据更改并通知您的列表适配器这些更改。您的列表适配器将更新屏幕上可见的行。

对于SimpleCursorAdapter,要么覆盖newView()/bindView(),要么使用ViewBinder,或者使用setViewValue() 和kin,如documentation 中所述。你可以覆盖getView(),但是你必须自己做行回收。

【讨论】:

嗨,谢谢 newView()/bindView(),我会试试的。我忘了说我不能使用 requery() 因为一个完全不同的 SQL 查询生成时间。【参考方案2】:

使用游标适配器代替基本适配器和数组适配器

【讨论】:

以上是关于如何提高(感知)使用 Android 创建复杂 ListView 的速度?的主要内容,如果未能解决你的问题,请参考以下文章

键盘感知滚动视图Android问题

提高组较复杂图论I

如何使用 Camera 2 API Android 提高捕获图像的质量?

Android LifeCycles之让组件感知生命周期的使用(生命周期观察者)

如何在 Android 的生命周期感知协程范围内返回函数值?

如何在 Android 中提高 Camera 2 的图像质量?