在Android应用程序中使用Kotlin频道和流实施搜索过滤器

Knowledge of Retrofit, Room, and Coroutines is a must for this guide.

对于本指南,必须具备改造,房间和协同程序的知识。

Part 1 of this Guide Here. (Not mandatory if you know how flows works)

本指南的第1部分 。 (如果您知道流程的工作原理,则不是强制性的)

让我们开始🏁 (Let’s Begin 🏁)

In this guide, we will add a search bar to the android application, which will query all the dog breeds in the database and update the flow based on out query using channels(Github repository here).

在本指南中,我们将向Android应用程序添加搜索栏,该搜索栏将查询数据库中的所有犬种,并基于使用渠道的查询( Github存储库 )更新流。

Image for post

当前架构 (Current Architecture)

On pressing the “Load More” button, we do a One Shot Request to fetch a dog breed using retrofit which we then save to the Database using Room.

按下“ 加载更多 ”按钮后,我们发出一个单次请求,以使用改造来获取狗的品种,然后使用Room将其保存到数据库中。

This triggers an emission of flow from database of List of Dogs which we then combine with another flow, convert to Live Data and then observe the livedata from the view. (Read More Here)

这触发了“狗名单”数据库的流发射,然后我们将其与另一个流合并 ,转换为实时数据 ,然后从视图中观察实时数据 。 ( 在这里阅读更多 )

Image for post

We use the database as the Single Source of Truth.

我们将数据库用作真理的唯一来源。

实施搜索 (Implementing Search)

In this guide we will implement a search bar, that will filter the breeds based on searched query. In the View or MainActivity.kt, pass the searched query to viewModel.setSearchQuery(it).

在本指南中,我们将实现一个搜索栏,该搜索栏将根据搜索到的查询过滤品种。 在View或MainActivity.kt中 ,将搜索到的查询传递给viewModel.setSearchQuery( it )

search.setOnQueryTextListener(object : SearchView.OnQueryTextListener, androidx.appcompat.widget.SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String?): Boolean {
                return true
            }


            override fun onQueryTextChange(newText: String?): Boolean {
                newText?.let { 
                  //Pass Search Query to this function in viewmodel
                  viewModel.setSearchQuery(it) 
                }
                return true
            }
        }
       )
 viewModel.dogListLiveData.observe(this, Observer {
            adapter.submitList(it)
        })

频道介绍 (Introducing Channels)

Channels are a part of the coroutines Library. Think of channels as a pipe. You can send data from one end and receive from another. They are very similar to Non Blocking Queues and can also be used to communicate between coroutines as they support suspending functions for sending as well as receiving data.

通道是协程库的一部分。 将渠道视为管道。 您可以从一端发送数据,也可以从另一端接收数据。 它们与非阻塞队列非常相似,还可以用于在协程之间进行通信,因为它们支持用于发送和接收数据的暂功能。

Our implementation will however require a very simple usage of Channels as we won’t be using any suspend functions for this purpose.

但是,我们的实现将需要非常简单地使用Channel,因为我们将不会为此目的使用任何挂起函数。

We will use a ConflatedBroadcastChannel as this will only broadcast the most recent sent element to all the subscribers.

我们将使用ConflatedBroadcastChannel因为它将仅向所有订阅者广播最近发送的元素。

private val searchChanel = ConflatedBroadcastChannel<String>()
//We will use a ConflatedBroadcastChannel as this will only broadcast 
//the most recent sent element to all the subscribers


fun setSearchQuery(search: String) {
//We use .offer() to send the element to all the subscribers.
        searchChanel.offer(search)
    }


//Observe this live Data from view and submit the list in adapter.
 val dogListLiveData = searchChanel.asFlow() //asFlow() converts received elements from broadcast channels into a flow.
        .flatMapLatest { search ->
            //We use flatMapLatest as we don't want flows of flows and 
            //we only want to query the latest searched string.
            mainActivityRepository.getSearchedDogs(search)
        }
        .catch { throwable ->
            _snackbar.value = throwable.message
        }.asLiveData()

合并和转换流 (Combining and Transforming Flows)

In MainActivityRepository.kt, combine the flow emitted by the database with another flow and perform a transformation on it in Dispatchers.Default thread.

MainActivityRepository.kt中,将数据库发出的流与另一个流合并,并在Dispatchers.Default线程中对其执行转换。

fun getSearchedDogs(search: String): Flow<List<Dog>> {
        return dogDao.getSearchedDogs(search) //Get searched dogs from Room Database
            //Combine the result with another flow
            .combine(topBreedsFlow) { dogs, topDogs ->
                dogs.applyToDog(topDogs)
            }
            .flowOn(Dispatchers.Default)
            //Return the latest values
            .conflate()
    }

In the interface DogDao.kt

DogDao.kt接口中

@Query("SELECT * FROM dog WHERE breed LIKE '%' || :search || '%'")
    fun getSearchedDogs(search: String?): Flow<List<Dog>>


  @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun save(dog: Dog)

you完成了 (And you’re done ✅)

You have implemented a search bar in an application that uses channels to communicate downstream to the database and emits a flow after filtering the query.

您已经在应用程序中实现了搜索栏,该应用程序使用通道与数据库进行下游通信,并在过滤查询后发出流。

Image for post

翻译自: https://proandroiddev.com/implementing-search-filter-using-kotlin-channels-and-flows-in-your-android-application-df7c96e58b19

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值