【问题标题】:Implementing (network) search android实现(网络)搜索android
【发布时间】:2019-07-15 13:47:35
【问题描述】:

我迷路了。

在过去的几天里,我试图了解在我的 Android 应用中实现网络搜索的最佳方式。

我想保留 MVVM 架构,但如果要求太多,我准备考虑替代方案。

我需要能够在页面中搜索。

一个很好的例子\指南将不胜感激。

谢谢。

【问题讨论】:

  • 这取决于您的 API 和您的数据量(以及您的要求)。例如,如果您可以在本地缓存所有数据,因为它大约有 20000 个项目,那么您甚至可以从 SQLite 本地查询并显示它。然后它不会通过网络调用完成并离线工作。

标签: android search searchview searchable


【解决方案1】:

使用 Android 的分页库,您可以完成分页网络搜索,并使用您的结果更新 RecyclerView。

假设您有一个 API,我们可以使用它来调用搜索查询。这将由您将实现的 DataSource 支持,它会在您滚动时提供新的结果页面。

interface MySearchApi {
    fun search(query: String, count: Int): PagedList<SearchResult>
}

我们得到的是一个PagedList,它会随着更多搜索结果的加载而更新。我们没有将其包装在 Rx Observable 或 LiveData 对象中,因为在这种情况下,我们不希望加载的数据发生变化。如果您正在查询某种可能随时更改结果的实时服务,您可能需要考虑这一点。

我们可以从我们的 ViewModel 对象中公开这个分页列表或 LiveData,并构建一个 PagedListAdapter 子类,该子类将在加载时使用新数据更新 RecyclerView。

class MySearchAdapter() :
        PagedListAdapter<SearchResult, SearchResultViewHolder>(DIFF_CALLBACK) {
    fun onBindViewHolder(holder: SearchResultViewHolder, position: Int) {
        val concert: SearchResult? = getItem(position)

        // Note that "searchResult" is a placeholder if it's null.
        holder.bindTo(searchResult)
    }

    companion object {
        private val DIFF_CALLBACK = object :
                DiffUtil.ItemCallback<Concert>() {
            // Concert details may have changed if reloaded from the database,
            // but ID is fixed.
            override fun areItemsTheSame(oldSearchResult: SearchResult,
                    newSearchResult: SearchResult) = oldSearchResult.id == newSearchResult.id

            override fun areContentsTheSame(oldSearchResult: SearchResult,
                    newSearchResult: Concert) = newSearchResult == newSearchResult
        }
    }
}

使用 RecyclerView 进行连接的方法与通常使用任何其他 Adapter 和 RecyclerView 一样,并且您的 PagedList 应该在需要新数据页面时通知您的 DataSource。

您可以阅读更多关于分页架构here

【讨论】:

  • 谢谢亚历克斯。实际上,我已经有了搜索功能。我的问题从搜索类型开始,我不想对每种类型都进行网络调用,但请稍等一下,看看用户是否输入了另一个字符或删除了。就像在带有 debounce 的 RxJave 中一样,另一个重要的事情是始终在列表中显示最新的结果。
  • Debounce 将是实现这一目标的好方法。在输入的每个字符上,您都可以在输入中发出文本。去抖动超时后,您将更改通知您的模型。然后,您可以发出一个新的搜索查询,并用这个新的替换旧的 pagedList(在这种情况下,我会使用前面提到的 LiveData>,然后在适当的地方观察它)。抱歉,您最初的问题听起来好像您还没有尝试过任何事情。将来,最好描述一下您到目前为止所做的事情。
  • 对不起。实际上我的问题是在将输入发送到数据源之前我不知道如何去抖动。 Paging Library 和 RxJava 的集成是我最苦恼的
  • 所以我认为我们可以将其分为 3 个部分:去抖动、更新数据源和显示数据。您可以在 VM 中进行去抖动,可能使用发布主题。当您的输入发生更改时,通过发布主题添加完整的输入文本。你可以去抖和订阅,当你得到一个新值时,你可以从你的 API 请求一个新的 PagedList。然后,您可以更新 ViewModel 的 LiveData,然后可以更新适配器的实现。您只需要观察这个 livedata,比如在活动中,并在获得新值时更新适配器。
  • 哇,Alex,非常感谢您这么快回复。有没有机会举个例子?
猜你喜欢
  • 2011-04-12
  • 2010-12-19
  • 2017-01-19
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多