0

我目前正在编写一个应用程序,其中 recyclerview 中的每个项目都有一个复选框。用户可以单击复选框来保存特定电影。

我想使用 Jetpack Datastore 来保存复选框的状态。我设置了首选项管理器,但我在片段中遇到了困难,因为后者没有对复选框的引用(复选框在项目布局中)

在下面,您将找到首选项管理器类、daoviewmodel(我正在使用另一个视图模型从 api 获取数据)以及显示 recyclerview 的片段之一。

任何帮助是极大的赞赏。谢谢!

首选项管理器.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 favorite = preferences[PreferencesKeys.FAVORITES] ?: false
            FilterPreferences(favorite)

        }

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

    }

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

    }


}



DaoViewModel.kt

package com.example.moviesapp.ui

import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.moviesapp.network.MoviesFavoritesRepository
import com.example.moviesapp.network.MoviesResults
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 preferencesFlow = preferencesManager.preferencesFlow

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

    }


    fun addMovieToFavs(movie: MoviesResults.Movies) {
        viewModelScope.launch {
            repository.insertFavorite(movie)

        }
    }

  

    fun getFavorites(): LiveData<List<MoviesResults.Movies>> {

        return repository.getFavorites()


    }
    


}




MoviesListFragment.kt

package com.example.moviesapp.ui.Fragments

import android.os.Bundle
import android.view.*
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.moviesapp.R
import com.example.moviesapp.databinding.FragmentMoviesListBinding
import com.example.moviesapp.network.MoviesResults
import com.example.moviesapp.ui.DaoViewModel
import com.example.moviesapp.ui.MovieApiStatus
import com.example.moviesapp.ui.MoviesListAdapter
import com.example.moviesapp.ui.MoviesListViewModel
import dagger.hilt.android.AndroidEntryPoint


@AndroidEntryPoint
class MoviesListFragment : Fragment(R.layout.fragment_movies_list), MoviesListAdapter.OnItemClickListener {


    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        return inflater.inflate(R.layout.fragment_movies_list, container, false)
    }



    private val daoViewModel by viewModels<DaoViewModel>()
    private val viewModel by viewModels<MoviesListViewModel>()
    private var _binding: FragmentMoviesListBinding? = null
    private val binding get() = _binding!!


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

        //View is inflated layout

        _binding = FragmentMoviesListBinding.bind(view)

        val adapter = MoviesListAdapter(this)
        var status: MovieApiStatus? = MovieApiStatus.LOADING

        binding.apply {
            recyclerView.layoutManager = LinearLayoutManager(requireContext())
            //Disable animations
            recyclerView.setHasFixedSize(true)
            recyclerView.adapter = adapter


        }
        //Observe the movies livedata
        //Use viewLifecycleOwner instead of this because the UI should stop being updated when the fragment view is destroyed
        viewModel.getTrending()

       viewModel.moviesTrending.observe(viewLifecycleOwner) {
           adapter.submitList(it)

       }

        viewModel.networkState.observe(viewLifecycleOwner, {
            binding.progressBar.isVisible = if (it==MovieApiStatus.LOADING) true else view.isGone
            binding.buttonRetry.isVisible = if(it==MovieApiStatus.ERROR) true else view.isGone
            binding.errorTextView.isVisible = if(it==MovieApiStatus.ERROR) true else view.isGone
            binding.recyclerView.isVisible =  if(it==MovieApiStatus.DONE) true else view.isGone
            binding.noResultsText.isVisible = false


        })





        //Display trending movies

        //loadstate is of type combined loadstates, which combines the loadstate of different scenarios(when we refresh dataset or when we append new data to it) into this one object
        //We can use it to check for these scenarios and make our views visible or unvisible according to it

        setHasOptionsMenu(true)
    }

    override fun  onItemClick(movie: MoviesResults.Movies) {
        val action = MoviesListFragmentDirections.actionMoviesListFragmentToMoviesDetailsFragment(movie)
        findNavController().navigate(action)
    }

    override fun onFavoriteClick(movie: MoviesResults.Movies, isChecked: Boolean) {
        daoViewModel.addMovieToFavs(movie)
    }




    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        super.onCreateOptionsMenu(menu, inflater)

        // Inflate the gallery menu
        inflater.inflate(R.menu.menu_gallery, menu)




    }





    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

}


4

0 回答 0