Rumah  >  Artikel  >  UI tidak dipasang semula selepas memadamkan semua item dalam jetpack menggunakan pangkalan data bilik

UI tidak dipasang semula selepas memadamkan semua item dalam jetpack menggunakan pangkalan data bilik

WBOY
WBOYke hadapan
2024-02-06 08:15:04537semak imbas
Kandungan soalan

Saya mempunyai apl filem yang dibina menggunakan karang jetpack. Di dalamnya saya menunjukkan filem kegemaran yang dipilih oleh pengguna. Kegemaran harus wujud dalam UI dengan sempurna, tetapi apabila saya memadamkan item daripada UI, UI tidak segera menyusun semula untuk mencerminkan perubahan. apa yang perlu dilakukan

Ini UI saya

@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)))}
        )
    }
}

Ini adalah model pandangan saya

@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()
     }
}

Jawapan betul


Masalahnya menjadi sangat jelas apabila anda melihat penggunaan bertulis _favs: Hanya getfavmovies akan mengemas kininya.

Walaupun ini terdengar seperti "anda harus mengemas kini keadaan UI anda dalam fungsi padam", saya ingin mencadangkan penyelesaian alternatif: Manfaatkan kuasa room + flows!

Tentukan dahulu loadingstate dalam model pandangan, yang akan disimpan sebagai strim:

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)

Kemudian, tukar fungsi getfavmovies() untuk menggunakan mekanisme ini:

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!!)
        }
    }
}

Akhir sekali, gabungkan status dan data anda untuk membuat keajaiban berlaku. Ini akan dikemas kini secara automatik apabila salah satu daripadanya berubah :)

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
    }
}

Penafian: Mungkin terdapat kesilapan ejaan dalam hal ini, saya tidak mempunyai idea yang berguna

Mari tamatkan jawapan ini dengan menambah baik kod:

  1. Elakkan menggunakan = untuk fungsi yang tidak mengembalikan apa-apa (= 用于不返回任何内容的函数(getfavmoviesinsertmoviedeletemovies)。否则,你会例如期望 getfavmovies, insertmovie, deletemovies). Jika tidak, anda akan menjangkakan

    untuk mengembalikan senarai filem
  2. remember { mutablestateof(movieviewmodel.getfavmovies()) } 并没有真正的 remember 任何东西,是吗?这太令人恼火了。我建议将其移至 viewmodel 中: init { movieviewmodel.getfavmovies() }

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

  4. mutablelist9fed9bb6bc0c66d7a13f33ab448de4c5。对 ui 状态使用可变值是一个坏主意,例如它可能会混淆您的 stateflowUistate anda mengandungi . Pastikan anda mengelakkan situasi ini. Hanya gunakan senarai lama yang biasa :) https://www.php.cn/link/ff685590317f1330efc73f396ac92cd7

  5. collectasstatewithlifecycle() 而不是 collectasstate()Gunakan . Lihat https://medium.com/androiddevelopers/consuming-flows - selamat dalam jetpack-compose-cde014d0d5a3

  6. repoimplAnda semestinya tidak boleh mengakses

    dalam model pandangan: keseluruhan idea untuk memisahkan repositori kepada antara muka dan pelaksanaan adalah untuk menyembunyikan pelaksanaan
  7. Adalah idea yang baik untuk mentakrifkan yang boleh digubah skrin, ia tidak memerlukan model pandangan, hanya data, serupa dengan 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
}

Atas ialah kandungan terperinci UI tidak dipasang semula selepas memadamkan semua item dalam jetpack menggunakan pangkalan data bilik. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam