如何观察JetPack中的MutableStateFlow列表组成

发布于 2025-02-07 12:04:34 字数 4018 浏览 2 评论 0原文

我必须在JetPack撰写上实现Google的“位置自动完成”,但问题是,一旦获得了位置列表,我就无法更新UI。

更详细地说,从Google API接收的位置存储在A mutableStateFlow< mutablelist< string>>>中,并且状态可通过:databaseviewModel.autococteplaces在可复合函数中观察到。 .CollectasState()。但是,当将新项目添加到列表中时,可组合函数不是重新编译的

类,可以获取位置:

class AutocompleteRepository(private val placesClient: PlacesClient)
{
    val autocompletePlaces = MutableStateFlow<MutableList<String>>(mutableListOf())

    fun fetchPlaces(query: String) {
        val token = AutocompleteSessionToken.newInstance()

        val request = FindAutocompletePredictionsRequest.builder()
            .setSessionToken(token)
            .setCountry("IT")
            .setQuery(query)
            .build()

        placesClient.findAutocompletePredictions(request).addOnSuccessListener {
                response: FindAutocompletePredictionsResponse ->
            autocompletePlaces.value.clear()
            for (prediction in response.autocompletePredictions) {
                autocompletePlaces.value.add(prediction.getPrimaryText(null).toString())
            }
        }
    }
}

viewModel:

class DatabaseViewModel(application: Application): AndroidViewModel(application) {

    val autocompletePlaces: MutableStateFlow<MutableList<String>>
    val autocompleteRepository: AutocompleteRepository

    init {
        Places.initialize(application, apiKey)
        val placesClient = Places.createClient(application)
        autocompleteRepository = AutocompleteRepository(placesClient)
        autocompletePlaces = autocompleteRepository.autocompletePlaces
    }

    fun fetchPlaces(query: String)
    {
        autocompleteRepository.fetchPlaces(query)
    }
}

可综合函数:编辑:

@Composable
fun dropDownMenu(databaseViewModel: DatabaseViewModel) {

    var placeList = databaseViewModel.autocompletePlaces.collectAsState()
    
    //From here on I don't think it's important, but I'll put it in anyway:
    var expanded by rememberSaveable { mutableStateOf(true) }
    var placeName by rememberSaveable { mutableStateOf("") }

    Column {
        OutlinedTextField(value = placeName, onValueChange =
        { newText ->
            placeName = newText
            databaseViewModel.fetchPlaces(newText)
        })

        DropdownMenu(expanded = expanded,
            onDismissRequest = { /*TODO*/ },
            properties = PopupProperties(
                focusable = false,
                dismissOnBackPress = true,
                dismissOnClickOutside = true)) {
            placeList.value.forEach { item ->
                DropdownMenuItem(text = { Text(text = item) },
                    onClick = {
                        placeName = item
                        expanded = false
                    })
            }
        }
    }
}

编辑: 通过更改解决:mutableStateFlow&lt; mutablelist&lt; string&gt;(mutableListof()) to mutableStateFlow&lt; list&lt; string&lt; string&gt;&gt;&gt;(Listof(Listof()) 't了解发生了什么变化,因为列表的结构在上一个代码中也发生了更改

class AutocompleteRepository(private val placesClient: PlacesClient)
{
    val autocompletePlaces = MutableStateFlow<List<String>>(listOf()) //Changed

    fun fetchPlaces(query: String) {
        val token = AutocompleteSessionToken.newInstance()

        val request = FindAutocompletePredictionsRequest.builder()
            .setSessionToken(token)
            .setCountry("IT")
            .setQuery(query)
            .build()

        val temp = mutableListOf<String>()
        placesClient.findAutocompletePredictions(request).addOnSuccessListener {
                response: FindAutocompletePredictionsResponse ->
            for (prediction in response.autocompletePredictions) {
                temp.add(prediction.getPrimaryText(null).toString())
            }
            autocompletePlaces.value = temp //changed
        }
    }
}

I have to implement Google's "Place Autocomplete" on Jetpack Compose, but the problem is that once I get the list of places, I can't update the UI.

Going into more detail, the places received from the google API are stored in a MutableStateFlow <MutableList <String>> and the status is observed in a Composable function via: databaseViewModel.autocompletePlaces.collectAsState(). However, when a new item is added to the list, the Composable function is not re-compiled

Class that gets the places:

class AutocompleteRepository(private val placesClient: PlacesClient)
{
    val autocompletePlaces = MutableStateFlow<MutableList<String>>(mutableListOf())

    fun fetchPlaces(query: String) {
        val token = AutocompleteSessionToken.newInstance()

        val request = FindAutocompletePredictionsRequest.builder()
            .setSessionToken(token)
            .setCountry("IT")
            .setQuery(query)
            .build()

        placesClient.findAutocompletePredictions(request).addOnSuccessListener {
                response: FindAutocompletePredictionsResponse ->
            autocompletePlaces.value.clear()
            for (prediction in response.autocompletePredictions) {
                autocompletePlaces.value.add(prediction.getPrimaryText(null).toString())
            }
        }
    }
}

ViewModel:

class DatabaseViewModel(application: Application): AndroidViewModel(application) {

    val autocompletePlaces: MutableStateFlow<MutableList<String>>
    val autocompleteRepository: AutocompleteRepository

    init {
        Places.initialize(application, apiKey)
        val placesClient = Places.createClient(application)
        autocompleteRepository = AutocompleteRepository(placesClient)
        autocompletePlaces = autocompleteRepository.autocompletePlaces
    }

    fun fetchPlaces(query: String)
    {
        autocompleteRepository.fetchPlaces(query)
    }
}

Composable function:

@Composable
fun dropDownMenu(databaseViewModel: DatabaseViewModel) {

    var placeList = databaseViewModel.autocompletePlaces.collectAsState()
    
    //From here on I don't think it's important, but I'll put it in anyway:
    var expanded by rememberSaveable { mutableStateOf(true) }
    var placeName by rememberSaveable { mutableStateOf("") }

    Column {
        OutlinedTextField(value = placeName, onValueChange =
        { newText ->
            placeName = newText
            databaseViewModel.fetchPlaces(newText)
        })

        DropdownMenu(expanded = expanded,
            onDismissRequest = { /*TODO*/ },
            properties = PopupProperties(
                focusable = false,
                dismissOnBackPress = true,
                dismissOnClickOutside = true)) {
            placeList.value.forEach { item ->
                DropdownMenuItem(text = { Text(text = item) },
                    onClick = {
                        placeName = item
                        expanded = false
                    })
            }
        }
    }
}

EDIT:
solved by changing: MutableStateFlow<MutableList<String>>(mutableListOf()) to MutableStateFlow<List<String>>(listOf()), but I still can't understand what has changed, since the structure of the list was also changed in the previous code

class AutocompleteRepository(private val placesClient: PlacesClient)
{
    val autocompletePlaces = MutableStateFlow<List<String>>(listOf()) //Changed

    fun fetchPlaces(query: String) {
        val token = AutocompleteSessionToken.newInstance()

        val request = FindAutocompletePredictionsRequest.builder()
            .setSessionToken(token)
            .setCountry("IT")
            .setQuery(query)
            .build()

        val temp = mutableListOf<String>()
        placesClient.findAutocompletePredictions(request).addOnSuccessListener {
                response: FindAutocompletePredictionsResponse ->
            for (prediction in response.autocompletePredictions) {
                temp.add(prediction.getPrimaryText(null).toString())
            }
            autocompletePlaces.value = temp //changed
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

べ繥欢鉨o。 2025-02-14 12:04:34

在您的旧代码中,您只是通过向其添加项目来更改mutablelist实例 stateflow 。这不会触发更新,因为它仍然是相同的列表(但其中包含额外的值)。

使用新代码,您将stateflow的全部值更改为触发更新的新列表。

您可以将新代码简化为类似:

autocompletePlaces.update { 
  it + response.autocompletePredictions.map { prediction ->
    prediction.getPrimaryText(null).toString()
  } 
}

In your old code you were just changing the MutableList instance inside the StateFlow by adding items to it. This does not trigger an update because it is still the same list (but with extra values in it).

With your new code you are changing the whole value of the StateFlow to a new list which triggers an update.

You can simplify your new code to something like:

autocompletePlaces.update { 
  it + response.autocompletePredictions.map { prediction ->
    prediction.getPrimaryText(null).toString()
  } 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文