Rumah > Java > teks badan

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

WBOY
Lepaskan: 2024-02-06 08:15:04
ke hadapan
545 orang telah melayarinya
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)))}
        )
    }
}
Salin selepas log masuk

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()
     }
}
Salin selepas log masuk


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)
Salin selepas log masuk

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!!)
        }
    }
}
Salin selepas log masuk

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
    }
}
Salin selepas log masuk

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. mutablelist<favmodel>。对 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
}
Salin selepas log masuk

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!

Label berkaitan:
sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan