[LeakCanary] ForYou*: Refactor to use viewBinding and viewModels

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2023-10-31 17:45:26 +05:30
parent 981774dce3
commit ca881413eb
3 changed files with 47 additions and 107 deletions

View File

@@ -20,32 +20,32 @@
package com.aurora.store.view.ui.commons package com.aurora.store.view.ui.commons
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModelProvider
import com.aurora.Constants import com.aurora.Constants
import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.App
import com.aurora.gplayapi.data.models.StreamBundle import com.aurora.gplayapi.data.models.StreamBundle
import com.aurora.gplayapi.data.models.StreamCluster import com.aurora.gplayapi.data.models.StreamCluster
import com.aurora.gplayapi.helpers.StreamHelper.Category
import com.aurora.gplayapi.helpers.StreamHelper.Type
import com.aurora.store.R import com.aurora.store.R
import com.aurora.store.data.ViewState import com.aurora.store.data.ViewState
import com.aurora.store.databinding.FragmentForYouBinding import com.aurora.store.databinding.FragmentForYouBinding
import com.aurora.store.view.custom.recycler.EndlessRecyclerOnScrollListener import com.aurora.store.view.custom.recycler.EndlessRecyclerOnScrollListener
import com.aurora.store.view.epoxy.controller.GenericCarouselController import com.aurora.store.view.epoxy.controller.GenericCarouselController
import com.aurora.store.viewmodel.homestream.AppsForYouViewModel
import com.aurora.store.viewmodel.homestream.BaseClusterViewModel import com.aurora.store.viewmodel.homestream.BaseClusterViewModel
import com.aurora.store.viewmodel.homestream.GamesForYouViewModel
class ForYouFragment : BaseFragment(), GenericCarouselController.Callbacks { class ForYouFragment : BaseFragment(R.layout.fragment_for_you),
GenericCarouselController.Callbacks {
private var _binding: FragmentForYouBinding? = null
private val binding get() = _binding!!
private val viewModel: BaseClusterViewModel by viewModels()
private lateinit var B: FragmentForYouBinding
private lateinit var C: GenericCarouselController private lateinit var C: GenericCarouselController
private lateinit var VM: BaseClusterViewModel
private lateinit var streamBundle: StreamBundle private lateinit var streamBundle: StreamBundle
private lateinit var endlessRecyclerOnScrollListener: EndlessRecyclerOnScrollListener
private var pageType = 0 private var pageType = 0
@@ -60,18 +60,9 @@ class ForYouFragment : BaseFragment(), GenericCarouselController.Callbacks {
} }
} }
override fun onCreateView( override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
inflater: LayoutInflater, super.onViewCreated(view, savedInstanceState)
container: ViewGroup?, _binding = FragmentForYouBinding.bind(view)
savedInstanceState: Bundle?
): View {
B = FragmentForYouBinding.bind(
inflater.inflate(
R.layout.fragment_for_you,
container,
false
)
)
C = GenericCarouselController(this) C = GenericCarouselController(this)
@@ -81,36 +72,39 @@ class ForYouFragment : BaseFragment(), GenericCarouselController.Callbacks {
} }
when (pageType) { when (pageType) {
0 -> VM = 0 -> viewModel.getStreamBundle(Category.APPLICATION, Type.HOME)
ViewModelProvider(requireActivity()).get(AppsForYouViewModel::class.java) 1 -> viewModel.getStreamBundle(Category.GAME, Type.HOME)
1 -> VM =
ViewModelProvider(requireActivity()).get(GamesForYouViewModel::class.java)
} }
return B.root binding.recycler.setController(C)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { viewModel.liveData.observe(viewLifecycleOwner) {
super.onViewCreated(view, savedInstanceState)
B.recycler.setController(C)
VM.liveData.observe(viewLifecycleOwner) {
when (it) { when (it) {
is ViewState.Empty -> { is ViewState.Empty -> {
} }
is ViewState.Loading -> { is ViewState.Loading -> {
updateController(null) updateController(null)
} }
is ViewState.Error -> { is ViewState.Error -> {
} }
is ViewState.Status -> { is ViewState.Status -> {
} }
is ViewState.Success<*> -> { is ViewState.Success<*> -> {
if (!::streamBundle.isInitialized) if (!::streamBundle.isInitialized) {
attachRecycler() binding.recycler.addOnScrollListener(
object : EndlessRecyclerOnScrollListener() {
override fun onLoadMore(currentPage: Int) {
viewModel.observe()
}
}
)
}
streamBundle = it.data as StreamBundle streamBundle = it.data as StreamBundle
@@ -120,15 +114,9 @@ class ForYouFragment : BaseFragment(), GenericCarouselController.Callbacks {
} }
} }
private fun attachRecycler() { override fun onDestroyView() {
endlessRecyclerOnScrollListener = super.onDestroyView()
object : EndlessRecyclerOnScrollListener() { _binding = null
override fun onLoadMore(currentPage: Int) {
VM.observe()
}
}
B.recycler.addOnScrollListener(endlessRecyclerOnScrollListener)
} }
private fun updateController(streamBundle: StreamBundle?) { private fun updateController(streamBundle: StreamBundle?) {
@@ -141,7 +129,7 @@ class ForYouFragment : BaseFragment(), GenericCarouselController.Callbacks {
} }
override fun onClusterScrolled(streamCluster: StreamCluster) { override fun onClusterScrolled(streamCluster: StreamCluster) {
VM.observeCluster(streamCluster) viewModel.observeCluster(streamCluster)
} }
override fun onAppClick(app: App) { override fun onAppClick(app: App) {

View File

@@ -36,12 +36,12 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
abstract class BaseClusterViewModel(application: Application) : BaseAndroidViewModel(application) { class BaseClusterViewModel(application: Application) : BaseAndroidViewModel(application) {
var authData: AuthData = AuthProvider.with(application).getAuthData() var authData: AuthData = AuthProvider.with(application).getAuthData()
var streamHelper: StreamHelper = StreamHelper(authData) var streamHelper: StreamHelper =
.using(HttpClient.getPreferredClient(application)) StreamHelper(authData).using(HttpClient.getPreferredClient(application))
val liveData: MutableLiveData<ViewState> = MutableLiveData() val liveData: MutableLiveData<ViewState> = MutableLiveData()
var streamBundle: StreamBundle = StreamBundle() var streamBundle: StreamBundle = StreamBundle()
@@ -49,15 +49,11 @@ abstract class BaseClusterViewModel(application: Application) : BaseAndroidViewM
lateinit var type: StreamHelper.Type lateinit var type: StreamHelper.Type
lateinit var category: StreamHelper.Category lateinit var category: StreamHelper.Category
open fun getStreamBundle( fun getStreamBundle(category: StreamHelper.Category, type: StreamHelper.Type) {
nextPageUrl: String, this.type = type
category: StreamHelper.Category, this.category = category
type: StreamHelper.Type liveData.postValue(ViewState.Loading)
): StreamBundle { observe()
return if (streamBundle.streamClusters.isEmpty())
streamHelper.getNavStream(type, category)
else
streamHelper.next(nextPageUrl)
} }
override fun observe() { override fun observe() {
@@ -67,11 +63,11 @@ abstract class BaseClusterViewModel(application: Application) : BaseAndroidViewM
if (!streamBundle.hasCluster() || streamBundle.hasNext()) { if (!streamBundle.hasCluster() || streamBundle.hasNext()) {
//Fetch new stream bundle //Fetch new stream bundle
val newBundle = getStreamBundle( val newBundle = if (streamBundle.streamClusters.isEmpty()) {
streamBundle.streamNextPageUrl, streamHelper.getNavStream(type, category)
category, } else {
type streamHelper.next(streamBundle.streamNextPageUrl)
) }
//Update old bundle //Update old bundle
streamBundle.apply { streamBundle.apply {

View File

@@ -1,44 +0,0 @@
/*
* Aurora Store
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
*
* Aurora Store is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Aurora Store is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.aurora.store.viewmodel.homestream
import android.app.Application
import com.aurora.gplayapi.helpers.StreamHelper
import com.aurora.store.data.ViewState
class AppsForYouViewModel(application: Application) : BaseClusterViewModel(application) {
init {
category = StreamHelper.Category.APPLICATION
type = StreamHelper.Type.HOME
liveData.postValue(ViewState.Loading)
observe()
}
}
class GamesForYouViewModel(application: Application) : BaseClusterViewModel(application) {
init {
category = StreamHelper.Category.GAME
type = StreamHelper.Type.HOME
liveData.postValue(ViewState.Loading)
observe()
}
}