当前位置: 首页 > 知识库问答 >
问题:

在Place API的适配器中的Filter.performFiltering()中使用Rx反跳运算符

林昱
2023-03-14

我们的应用程序有AutoCompleteTextView用于搜索地点,与谷歌地点API。

我想在PLACE SEARCH中添加debounce RxJava操作符。我不太擅长RxJava。

适配器实现了getFilter(),而过滤器具有performFiltering(),它将约束/查询作为字符串接收
过滤器当前的外观如下:

private inner class AutocompleteFilter : Filter() {

    @WorkerThread
    override fun performFiltering(constraint: CharSequence?): Filter.FilterResults {
        val results = Filter.FilterResults()
        val search = constraint?.toString() ?: ""

        var found = emptyList<PlaceData>()

        // quick reply on empty search
        val bounds = latLngBounds
        if (!TextUtils.isEmpty(search) && bounds != null) {
            found = placesApiHelper.fetchAutocompletePredictions(search, bounds)
                    .timeout(1000L, TimeUnit.MILLISECONDS)
                    .toList()
                    .doOnError {
                        searchResultSubject.onNext(false)
                        logTo(log).warning("Timeout or error happens. %s", it)
                    }
                    .doOnSuccess {
                        searchResultSubject.onNext(true)
                    }
                    .onErrorReturn { emptyList() }
                    .blockingGet()
        }

        results.values = found
        results.count = found.size

        return results
    }

    @MainThread
    override fun publishResults(constraint: CharSequence?, results: Filter.FilterResults) {
        logTo(log).info("publishing results. Found: %s items", results.count)

        data.clear()

        val list = results.values as? List<*>
        list?.let {
            val values = it.filterIsInstance<PlaceData>()
            if (values.isNotEmpty()) {
                data.addAll(values)
                notifyDataSetChanged()
            }
        }
    }
}

和fetchAutoCompletePreVII()如下所示:

 private fun fetchAutocompletePredictions(query: String, latLngBounds: LatLngBounds): Observable<PlaceData> {
    Timber.d("places api request: %s (total: %s, cached: %s)", query, PlacesApiCache.CALLS.incrementAndGet(), PlacesApiCache.HITS.get())

    val rectangularBounds = toRectangularBounds(latLngBounds)

    val request = FindAutocompletePredictionsRequest.builder()
            .setLocationBias(rectangularBounds)
            .setQuery(query)
            .build()

    return Observable.create {
        placesClient.findAutocompletePredictions(request).addOnSuccessListener { response ->

            val predictions = response.autocompletePredictions
            val results = mutableListOf<PlaceData>()

            for (i in 0 until Math.min(predictions.size, MAX_RESULTS)) {
                results.add(placeDataFrom(predictions[i]))
            }

            PlacesApiCache.cacheData(query, results)

            for (result in results) {
                it.onNext(result)
            }

            it.onComplete()
        }.addOnFailureListener { exception ->
            if (exception is ApiException) {
                Timber.e("Place not found: %s", exception.getStatusCode())
            }
            it.onError(exception)
        }
    }
}

我试图使用PublichSubject(来自JakeWharton库的PublishRelay),但我仍然没有信心修复它,因为EVENT通过这个调用(获取约束)发生在这里,同样的方法也应该返回FIlterResult。这意味着观察者也应该被放置在performFiltering()中。这意味着对于每个字母条目,此方法都会命中,因此会有多个观察者。
而且,我应该以相同的方法cal subject.onNext()作为新的搜索查询(约束)只在这里知道。

在这种情况下,如何使用防抖运算符使整个过程同步,在结束时返回FIlter结果?

提前致谢!

共有1个答案

燕英奕
2023-03-14

我去掉了过滤器。我没有让过滤器回调收到有关新搜索字符串的通知,而是添加了自己的Publishsubject,它观察新的搜索字符串并通知观察者。

自己的观察者(与公共主题而不是过滤器回调)允许我在流中插入防抖运算符。

在适配器中添加了这个:

private var queryPlacesSubject = PublishSubject.create<String>()

init {
    subscribeForPlacePredictions()
}

private fun subscribeForPlacePredictions() {
    queryPlacesSubject
            .debounce(DEBOUNCE_TIME_MILLIS, TimeUnit.MILLISECONDS)
            .distinctUntilChanged()
            .observeOn(Schedulers.newThread())
            .doOnNext { findPlacePredictions(it) }
            .observeOn(AndroidSchedulers.mainThread())
            .doOnNext {notifyThePlacesChanged()}
            .subscribeOn(Schedulers.io())
            .subscribe()
}

fun setQuery(query: String) {
    queryPlacesSubject.onNext(query)
}

然后这两个在适配器中:

    private fun findPlacePredictions(query: String?) {
    val search = query ?: ""

    // save entered text by user for highlight operations
    highlight = search

    // we should be in background thread already
    var found = emptyList<PlaceData>()

    // quick reply on empty search
    val bounds = latLngBounds
    if (!TextUtils.isEmpty(search) && bounds != null) {
        found = placesApiHelper.requestAutocomplete(search, bounds)
                .timeout(runtime.timeoutAutocompleteSearch(), TimeUnit.MILLISECONDS)
                .toList()
                .doOnError {
                    searchResultSubject.onNext(false)
                    logTo(log).warning("Timeout or error happens. %s", it)
                }
                .doOnSuccess {
                    searchResultSubject.onNext(true)
                }
                .onErrorReturn { emptyList() }
                .blockingGet()
    }

    data.clear()
    data.addAll(found)
}

private fun notifyThePlacesChanged() {
    notifyDataSetChanged()
}

已将“我的演示者”中的新搜索字符串设置为“主题”:

adapter.setQuery(currText)
 类似资料:
  • 但正在记录错误消息: 15: 25:53.476 E/RecyclerView:未连接适配器;跳过布局 15:25:53.655E/RecyClerView:未连接适配器;跳过布局

  • 我有一块碎片。加载的视图的onCreateView方法上的这个片段有一个ListView(a)(在适配器(a)中填充)。但是,此ListView(A)中有另一个ListView(B)。所以现在,我必须调用适配器(B)来填充这个listview(B)。如果我从片段调用它,我会得到一个空指针,如果我从适配器调用它(a),它不会崩溃,但不会工作。 如何调用另一个适配器中的适配器。 这是片段的代码: 其中

  • 这是日志,该日志显示的次数与ItemView的编号相同。但我的应用程序还在正常运行。

  • 本文向大家介绍rx-java onBackpressureXXX运算子,包括了rx-java onBackpressureXXX运算子的使用技巧和注意事项,需要的朋友参考一下 示例 大多数开发人员在应用程序失败时会遇到背压,MissingBackpressureException并且异常通常指向observeOn运算符。实际原因通常是对的非背压使用PublishSubject,timer()或者i

  • 我有一个微调器,其元素保存在共享引用中。当我从微调器中选择任何元素并单击“保存”按钮时,它会将该元素保存在SharedRef中,并且每当我返回此活动时,微调器将与我选择并保存的相同元素一起被选中。当我关闭应用程序并从手机中当前运行的应用程序中删除时,问题就会出现。在这种情况下,当我打开应用程序并转到该活动时,将使用第0个元素选择微调器。我正在从SharedRef获取保存的元素,但未调用getPos

  • 我有购物车活动,用户可以在其中添加,更新和删除他们的购物车。每个函数都有它拥有java活动,我也有CartAdapter活动。我想执行一个计算,该计算可以在 ViewCart 活动中显示客户项目的总价。我在购物车适配器上进行了计算,但是在ViewCart活动中显示总价格时遇到问题。 我得到的错误是 java.lang.数字格式异常:对于输入字符串:"99.00"在java.lang.Integer