0

現在、recyclerview 内の各項目にチェックボックスがあるアプリを作成しています。ユーザーはチェックボックスをクリックして、特定のムービーを保存できます。

Jetpack Datastore を使用して、チェックボックスの状態を保存したいと考えています。設定マネージャーをセットアップしましたが、フラグメントはチェックボックスへの参照を保持していないため、フラグメントで苦労しています (チェックボックスは項目レイアウトにあります)。

以下に、設定マネージャー クラス、daoviewmodel (API からデータを取得するために別のビューモデルを使用しています)、および recyclerview を表示するフラグメントの 1 つがあります。

どんな助けでも大歓迎です。ありがとうございました!

PreferencesManager.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