0

我目前正在编写一个显示电影列表的应用程序。

我正在使用带有 3 个选项卡的底部导航栏:趋势、发现和收藏夹。每个都显示电影列表,用户可以按下电影并转到详细信息片段。详细信息片段有一个复选框,可以将电影添加到收藏夹选项卡。

复选框有效,电影已添加到收藏夹,但复选框状态有问题。例如,如果我从详细信息片段(例如从趋势选项卡)添加电影,然后转到收藏夹选项卡并按电影以转到详细信息片段,则不会选中。

此外,如果我回到趋势并按下电影,它也不会被检查。

任何帮助是极大的赞赏。

MoviesDetailsFragment.kt

package com.example.moviesapp.ui.Fragments

import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.navArgs
import com.bumptech.glide.Glide
import com.example.moviesapp.R
import com.example.moviesapp.databinding.FragmentMoviesDetailsBinding
import com.example.moviesapp.network.MoviesFavorites
import com.example.moviesapp.network.MoviesResults
import com.example.moviesapp.ui.DaoViewModel
import com.example.moviesapp.ui.IMAGE_BASE_URL
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch

@AndroidEntryPoint
class MoviesDetailsFragment() : Fragment(R.layout.fragment_movies_details) {


    //We can get the movies from the args property
    private val args by navArgs<MoviesDetailsFragmentArgs>()
    private val daoViewModel by viewModels<DaoViewModel>()
    private fun showToast(string: String) {
        Toast.makeText(view?.context, string, Toast.LENGTH_SHORT).show()

    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val binding = FragmentMoviesDetailsBinding.bind(view)





        binding.apply {
            val movie: MoviesResults.Movies = args.movie
            val fav = MoviesFavorites(
                movie.title,
                movie.id,
                movie.release_date,
                movie.overview,
                movie.vote_average,
                movie.poster_path,
                movie.original_language,
                movie.isFavorite,
            )
            //When you are in fragment/activity, pass it to a glide.with because view is less efficient
            Glide.with(this@MoviesDetailsFragment)
                .load(IMAGE_BASE_URL + movie.poster_path)
                //Have the textview visible only when image is visible
                .error(R.drawable.ic_baseline_error_outline_24)
                .fitCenter()
                .into(coverPhoto)

            title.text = movie.title
            releaseDate.text = movie.release_date
            language.text = movie.original_language
            rating.text = movie.vote_average
            plot.text = movie.overview



            viewLifecycleOwner.lifecycleScope.launch {

                fav.isFavorite = daoViewModel.preferencesFlow.first().favorite


            }




            favCheckbox.setOnClickListener {


                if (favCheckbox.isChecked) {


                    fav.isFavorite = true
                    daoViewModel.addMovieToFavs(fav)
                    showToast("${fav.title} is added to your favorites")

                } else {


                    fav.isFavorite = false
                    daoViewModel.deleteMovieFromFavs(fav)
                    showToast("${fav.title} is removed from your favorites")


                }


            }
        }


    }


}


DaoViewModel.kt


package com.example.moviesapp.ui

import androidx.lifecycle.*
import com.example.moviesapp.network.MoviesFavorites
import com.example.moviesapp.network.MoviesFavoritesRepository
import com.example.moviesapp.network.PreferencesManager
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject




@HiltViewModel
class DaoViewModel @Inject constructor(
    private val repository: MoviesFavoritesRepository,
    private val preferencesManager: PreferencesManager
) :
    ViewModel() {


    val favMovies: LiveData<List<MoviesFavorites>> = repository.favoriteMovies.asLiveData()

    val preferencesFlow = preferencesManager.preferencesFlow

    fun onFavorite(favorite: Boolean) {
        viewModelScope.launch {
            preferencesManager.updateFavorite(favorite)
        }

    }


    fun addMovieToFavs(favorite: MoviesFavorites) {
        viewModelScope.launch {
            repository.insertFavorite(favorite)

        }
    }

    fun deleteMovieFromFavs(favorite: MoviesFavorites) {
        viewModelScope.launch {
            repository.deleteFavorite(favorite)
        }

    }


    class DaoViewModelFactory @Inject constructor(
        private val repository: MoviesFavoritesRepository,
        private val preferencesManager: PreferencesManager
    ) : ViewModelProvider.Factory {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            if (modelClass.isAssignableFrom(DaoViewModel::class.java)) {
                @Suppress("UNCHECKED_CAST")
                return DaoViewModel(repository, preferencesManager) as T
            }
            throw IllegalArgumentException("Unknown ViewModel class")

        }


    }


}






首选项管理器.kt

package com.example.moviesapp.network

import android.content.Context
import android.util.Log
import androidx.datastore.preferences.createDataStore
import androidx.datastore.preferences.edit
import androidx.datastore.preferences.emptyPreferences
import androidx.datastore.preferences.preferencesKey
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.map
import java.io.IOException
import javax.inject.Inject
import javax.inject.Singleton

private const val TAG = "PreferencesManager"


data class FilterPreferences(val favorite: Boolean)

@Singleton
class PreferencesManager @Inject constructor(@ApplicationContext context: Context) {


    private val dataStore = context.createDataStore("user_preferences")

    val preferencesFlow = dataStore.data
        .catch { exception ->
            if (exception is IOException) {
                Log.e(TAG, "Error reading preferences", exception)
                emit(emptyPreferences())

            } else {
                throw exception

            }


        }
        .map { preferences ->
            val favorites = preferences[PreferencesKeys.FAVORITES] ?: false
            FilterPreferences(favorites)

        }

    suspend fun updateFavorite(favorites: Boolean) {
        dataStore.edit { preferences ->
            preferences[PreferencesKeys.FAVORITES] = favorites
        }

    }

    private object PreferencesKeys {
        val FAVORITES = preferencesKey<Boolean>("favorites")

    }


}


4

0 回答 0