Refactor RecipesFragment
This commit extracts SwipeRefreshLayout extension to a separate file. Additionally, it refactors RecipesFragment in order to move all the logic to the ViewModel from the View.
This commit is contained in:
@@ -1,22 +1,43 @@
|
||||
package gq.kirmanak.mealient.ui.recipes
|
||||
|
||||
import android.widget.ImageView
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.paging.cachedIn
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import gq.kirmanak.mealient.data.recipes.RecipeImageLoader
|
||||
import gq.kirmanak.mealient.data.recipes.RecipeRepo
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.RecipeSummaryEntity
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class RecipeViewModel @Inject constructor(
|
||||
recipeRepo: RecipeRepo,
|
||||
private val recipeRepo: RecipeRepo,
|
||||
private val recipeImageLoader: RecipeImageLoader
|
||||
) : ViewModel() {
|
||||
val recipeFlow = recipeRepo.createPager().flow
|
||||
private var _isRefreshing = MutableLiveData<Boolean>()
|
||||
val isRefreshing: LiveData<Boolean> get() = _isRefreshing
|
||||
|
||||
private val _nextRecipeInfoChannel = Channel<RecipeSummaryEntity>()
|
||||
val nextRecipeInfo: Flow<RecipeSummaryEntity> =
|
||||
_nextRecipeInfoChannel.receiveAsFlow()
|
||||
|
||||
val adapter = RecipesPagingAdapter(this) {
|
||||
Timber.d("onClick: recipe clicked $it")
|
||||
viewModelScope.launch { _nextRecipeInfoChannel.send(it) }
|
||||
}
|
||||
|
||||
init {
|
||||
setupAdapter()
|
||||
}
|
||||
|
||||
fun loadRecipeImage(view: ImageView, recipeSummary: RecipeSummaryEntity?) {
|
||||
Timber.v("loadRecipeImage() called with: view = $view, recipeSummary = $recipeSummary")
|
||||
@@ -24,4 +45,21 @@ class RecipeViewModel @Inject constructor(
|
||||
recipeImageLoader.loadRecipeImage(view, recipeSummary?.slug)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupAdapter() {
|
||||
with(viewModelScope) {
|
||||
launch {
|
||||
recipeRepo.createPager().flow.cachedIn(this).collect {
|
||||
Timber.d("setupAdapter: received data update")
|
||||
adapter.submitData(it)
|
||||
}
|
||||
}
|
||||
launch {
|
||||
adapter.onPagesUpdatedFlow.collect {
|
||||
Timber.d("setupAdapter: pages have been updated")
|
||||
_isRefreshing.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,11 @@ import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.RecipeSummaryEntity
|
||||
import gq.kirmanak.mealient.databinding.FragmentRecipesBinding
|
||||
import gq.kirmanak.mealient.ui.SwipeRefreshLayoutHelper.listenToRefreshRequests
|
||||
import gq.kirmanak.mealient.ui.auth.AuthenticationViewModel
|
||||
import gq.kirmanak.mealient.ui.refreshesLiveData
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import timber.log.Timber
|
||||
@@ -74,22 +73,19 @@ class RecipesFragment : Fragment() {
|
||||
|
||||
private fun setupRecipeAdapter() {
|
||||
Timber.v("setupRecipeAdapter() called")
|
||||
binding.recipes.layoutManager = LinearLayoutManager(requireContext())
|
||||
val adapter = RecipesPagingAdapter(viewModel) { navigateToRecipeInfo(it) }
|
||||
binding.recipes.adapter = adapter
|
||||
viewLifecycleOwner.lifecycleScope.launchWhenResumed {
|
||||
viewModel.recipeFlow.collect {
|
||||
Timber.d("Received update")
|
||||
adapter.submitData(it)
|
||||
}
|
||||
binding.recipes.adapter = viewModel.adapter
|
||||
viewModel.isRefreshing.observe(viewLifecycleOwner) {
|
||||
Timber.d("setupRecipeAdapter: isRefreshing = $it")
|
||||
binding.refresher.isRefreshing = it
|
||||
}
|
||||
binding.refresher.refreshesLiveData().observe(viewLifecycleOwner) {
|
||||
Timber.d("setupRecipeAdapter: received refresh request")
|
||||
viewModel.adapter.refresh()
|
||||
}
|
||||
viewLifecycleOwner.lifecycleScope.launchWhenResumed {
|
||||
adapter.listenToRefreshRequests(binding.refresher)
|
||||
}
|
||||
viewLifecycleOwner.lifecycleScope.launchWhenResumed {
|
||||
adapter.onPagesUpdatedFlow.collect {
|
||||
Timber.d("Pages have been updated")
|
||||
binding.refresher.isRefreshing = false
|
||||
viewModel.nextRecipeInfo.collect {
|
||||
Timber.d("setupRecipeAdapter: navigating to recipe $it")
|
||||
navigateToRecipeInfo(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user