Heim  >  Artikel  >  Die Benutzeroberfläche wurde nach dem Löschen aller Elemente im Jetpack mithilfe der Raumdatenbank nicht neu zusammengesetzt

Die Benutzeroberfläche wurde nach dem Löschen aller Elemente im Jetpack mithilfe der Raumdatenbank nicht neu zusammengesetzt

WBOY
WBOYnach vorne
2024-02-06 08:15:04537Durchsuche
Frageninhalt

Ich habe eine Film-App, die mit Jetpack Compose erstellt wurde. Darin zeige ich die vom Benutzer ausgewählten Lieblingsfilme. Die Favoriten sollten in der Benutzeroberfläche einwandfrei vorhanden sein, aber wenn ich ein Element aus der Benutzeroberfläche lösche, wird die Benutzeroberfläche nicht sofort neu organisiert, um die Änderungen widerzuspiegeln. was zu tun?

Das ist meine Benutzeroberfläche

@composable
fun favscreen(
    movieviewmodel: movieviewmodel
) {

    remember { mutablestateof(movieviewmodel.getfavmovies()) }
    val shouldshowdialog = remember { mutablestateof(false) }
    val uistates = movieviewmodel.favs.collectasstate()


    column {
        row {
            text(
                text = "fav movies",
                fontsize = 25.sp,
                fontfamily = fontfamily(font(r.font.nsb)),
                modifier = modifier.padding(20.dp).weight(1f)
            )

            iconbutton(onclick = {
                shouldshowdialog.value  = true
            }) {
                icon(icons.filled.delete, contentdescription = "")
            }
        }
        when(val currentstate = uistates.value){
            is movieviewmodel.uistates.loading -> {
                box(modifier = modifier.fillmaxsize(), contentalignment = alignment.center) {
                    circularprogressindicator()
                }
            }
            is movieviewmodel.uistates.favs -> {
                val data = currentstate.data
                if(data.isempty()){
                    box(modifier = modifier.fillmaxsize(), contentalignment = alignment.center) {
                        text(
                            text = "no fav movies",
                            fontsize = 25.sp,
                            fontfamily = fontfamily(font(r.font.nsb)),
                            modifier = modifier.padding(20.dp))
                    }
                }
                else {
                    lazycolumn(){
                        items(data){ fav ->
                            row(modifier = modifier
                                .padding(20.dp)
                                .fillmaxwidth()
                                .clip(roundedcornershape(16.dp))
                                .background(color = color.darkgray)) {
                                asyncimage(
                                    model = utils.image_url + fav.imageurl,
                                    contentdescription = "",
                                    contentscale = contentscale.crop,
                                    filterquality = filterquality.high,
                                    modifier = modifier
                                        .width(150.dp)
                                        .height(150.dp))

                                column(modifier = modifier.padding(20.dp)) {
                                    text(
                                        text = fav.title!!,
                                        fontsize = 20.sp,
                                        fontfamily = fontfamily(font(r.font.nsb)))
                                    text(
                                        text = fav.rating.tostring() + "/10 imdb",
                                        fontsize = 15.sp,
                                        fontfamily = fontfamily(font(r.font.nsb)))
                                    text(
                                        text = "movie id : #" + fav.movieid,
                                        fontsize = 15.sp,
                                        fontfamily = fontfamily(font(r.font.nsb)))
                                }
                            }
                        }
                    }
                }
            }
            is movieviewmodel.uistates.error -> {
                box(modifier = modifier.fillmaxsize(), contentalignment = alignment.center){
                    text(
                        text = "no fav movies",
                        fontsize = 25.sp,
                        fontfamily = fontfamily(font(r.font.nsb)),
                        modifier = modifier.padding(20.dp))
                }
            }
            else -> {}
        }
    }
    if (shouldshowdialog.value){
        alertdialog(
            ondismissrequest = { shouldshowdialog.value = false },
            confirmbutton = {
                textbutton(onclick = {
                    movieviewmodel.deletemovies()
                    shouldshowdialog.value = false
                }) {
                    text(text = "proceed", fontfamily = fontfamily(font(r.font.nsm)))
                }
            },
            dismissbutton = {
                textbutton(onclick = {
                    shouldshowdialog.value = false
                }) {
                    text(text = "cancel", fontfamily = fontfamily(font(r.font.nsm)))
                }
            },
            shape = roundedcornershape(16.dp),
            text = { text(text = "favs deletion",fontfamily = fontfamily(font(r.font.nsb)))},
            title = { text(text = "do you want to delete all fav movies ?", fontfamily = fontfamily(font(r.font.nsb)))}
        )
    }
}

Das ist mein Ansichtsmodell

@HiltViewModel
class MovieViewModel @Inject constructor(
    private val movieRepoImpl: MovieRepoImpl
) : ViewModel() {
    

    private val _favs : MutableStateFlow<UiStates> = MutableStateFlow(UiStates.INITIAL)
    val favs get() = _favs.asStateFlow()


    // MOVIE DAO
    fun getFavMovies() = viewModelScope.launch {
        try {
            _favs.value = UiStates.LOADING
            movieRepoImpl.getFavs().collectLatest {
                _favs.value = UiStates.FAVS(it)
            }
        } catch (ex : Exception){
            _favs.value = UiStates.ERROR(ex.localizedMessage!!)
        }

    }
    fun insertMovie(favModel: FavModel) = viewModelScope.launch {
        movieRepoImpl.insertFav(favModel)
    }
    fun deleteMovies() = viewModelScope.launch {
        movieRepoImpl.deleteAllMovies()
    }

     sealed class UiStates {
         object LOADING : UiStates()
         data class FAVS(val data : MutableList<FavModel>) : UiStates()
         data class ERROR(val error : String) : UiStates()
         object INITIAL : UiStates()
     }
}

Richtige Antwort


Das Problem wird sehr deutlich, wenn man sich die schriftliche Verwendung von _favs ansieht: Nur getfavmovies wird es aktualisieren.

Während das klingt wie „Sie sollten Ihren UI-Status in der Löschfunktion aktualisieren“, möchte ich eine alternative Lösung vorschlagen: Nutzen Sie die Kraft von room + flows!

Definieren Sie zunächst loadingstate im Ansichtsmodell, das als Stream gespeichert wird:

sealed class loadingstate {
  object loading : loadingstate()
  data class success : loadingstate()
  data class error(val error : string) : loadingstate()
  object initial : loadingstate()
}

private val loadingstate = mutablestateflow<loadingstate>(initial)

Ändern Sie dann die getfavmovies()-Funktion, um diesen Mechanismus zu verwenden:

fun getfavmovies() {
    viewmodelscope.launch {
        try {
            _loadingstate.value = loadingstate.loading
            movierepoimpl.loadfavs() // a function which triggers e.g. a network call to actually load your movies
            _loadingstate.value = loadingstate.success
        } catch (ex: exception) {
            _loadingstate.value = loadingstate.error(ex.localizedmessage!!)
        }
    }
}

Kombinieren Sie abschließend Ihren Status und Ihre Daten, um Magie zu verwirklichen. Dies wird automatisch aktualisiert, sobald sich einer von ihnen ändert :)

val favs: flow<uistates> = combine(
    movierepoimpl.getmovies(),
    loadingstate
) { movies, loadingstate ->
    when (loadingstate) {
        is loadingstate.loading -> uistates.loading
        is loadingstate.success -> uistates.success(movies)
        is loadingstate.error -> uistates.error(error)
        is loadingstate. initial -> uistates.initial
    }
}

Haftungsausschluss: Möglicherweise sind darin Rechtschreibfehler enthalten, ich habe keine Idee zur Hand

Beenden wir diese Antwort, indem wir den Code verbessern:

  1. Vermeiden Sie die Verwendung von = für Funktionen, die nichts zurückgeben (= 用于不返回任何内容的函数(getfavmoviesinsertmoviedeletemovies)。否则,你会例如期望 getfavmovies, insertmovie, deletemovies). Andernfalls würden Sie beispielsweise erwarten, dass

    eine Liste mit Filmen
  2. zurückgibt
  3. remember { mutablestateof(movieviewmodel.getfavmovies()) } 并没有真正的 remember 任何东西,是吗?这太令人恼火了。我建议将其移至 viewmodel 中: init { movieviewmodel.getfavmovies() }

  4. val uistates = movieviewmodel.favs.collectasstate():命名意味着这是多个 ui 状态,请使用单数; uistates 类本身也是如此。另外,如果这里直接使用“.value”,可以跳过这里的重新声明:when(val currentstate = uistates.value)

  5. mutablelist9fed9bb6bc0c66d7a13f33ab448de4c5。对 ui 状态使用可变值是一个坏主意,例如它可能会混淆您的 stateflowIhr Uistate enthält . Vermeiden Sie diese Situation unbedingt. Benutzen Sie einfach die einfache alte Liste :) https://www.php.cn/link/ff685590317f1330efc73f396ac92cd7

  6. collectasstatewithlifecycle() 而不是 collectasstate()Verwenden Sie . Siehe https://medium.com/androiddevelopers/sumption-flows – sicher in jetpack-compose-cde014d0d5a3

  7. repoimplSie sollten im Ansichtsmodell auf keinen Fall auf

    zugreifen: Die ganze Idee der Aufteilung des Repositorys in Schnittstellen und Implementierungen besteht darin, die Implementierung zu verbergen
  8. Es ist eine gute Idee, ein Screen-Composeable zu definieren, es erfordert kein Ansichtsmodell, sondern nur Daten, ähnlich wie https://developer.android.com/jetpack/compose/state#state-hoisting

    :

.🎜
@Composable
private fun FavScreen(
  val viewModel: MovieViewModel,
) {
  FawScreen(
    uiState = viewModel.fav.collectAsStateWithLifecycle().value,
    shouldShowDialog = viewModel.shouldShowDialog.collectAsStateWithLifecycle().value
  )
}

@Composable
private fun FavScreen(
  val uiState: UiStates,
  val shouldShowDialog: Boolean
) {
  // your current ui
}

Das obige ist der detaillierte Inhalt vonDie Benutzeroberfläche wurde nach dem Löschen aller Elemente im Jetpack mithilfe der Raumdatenbank nicht neu zusammengesetzt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen