Implement view model provider, local database
This commit is contained in:
parent
ec25b03e98
commit
77d7056962
@ -4,6 +4,7 @@
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name=".PokeSearch"
|
||||
android:allowBackup="true"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
|
21
app/src/main/java/com/ti/mobpo/AppViewModelProvider.kt
Normal file
21
app/src/main/java/com/ti/mobpo/AppViewModelProvider.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package com.ti.mobpo
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.createSavedStateHandle
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.ti.mobpo.ui.pokesearch.PokeSearchViewModel
|
||||
|
||||
object AppViewModelProvider {
|
||||
val Factory = viewModelFactory {
|
||||
initializer {
|
||||
PokeSearchViewModel(
|
||||
pokesearchApplication().appContainer.favouritesRepository
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun CreationExtras.pokesearchApplication(): PokeSearch =
|
||||
(this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as PokeSearch)
|
19
app/src/main/java/com/ti/mobpo/PokeSearch.kt
Normal file
19
app/src/main/java/com/ti/mobpo/PokeSearch.kt
Normal file
@ -0,0 +1,19 @@
|
||||
package com.ti.mobpo
|
||||
|
||||
import android.app.Application
|
||||
import com.ti.mobpo.data.AppContainer
|
||||
import com.ti.mobpo.data.AppDataContainer
|
||||
|
||||
class PokeSearch : Application() {
|
||||
lateinit var appContainer: AppContainer
|
||||
private set
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
appContainer = createAppContainer()
|
||||
}
|
||||
|
||||
private fun createAppContainer(): AppContainer {
|
||||
return AppDataContainer(this)
|
||||
}
|
||||
}
|
@ -17,4 +17,7 @@ interface FavouriteDao {
|
||||
|
||||
@Query("SELECT id FROM favourites")
|
||||
fun getAllFavoriteIds(): Flow<List<Int>>
|
||||
|
||||
@Query("SELECT EXISTS(SELECT 1 FROM favourites WHERE id = :id LIMIT 1)")
|
||||
suspend fun isFavourite(id: Int): Boolean
|
||||
}
|
||||
|
@ -20,4 +20,10 @@ interface FavouritesRepository {
|
||||
* Delete item from the data source
|
||||
*/
|
||||
suspend fun deleteItem(item: Favourite)
|
||||
|
||||
/**
|
||||
* Check if the item is a favourite
|
||||
*/
|
||||
|
||||
suspend fun isFavourite(id: Int): Boolean
|
||||
}
|
||||
|
@ -13,4 +13,8 @@ class OfflineFavouritesRepository(private val favouriteDao: FavouriteDao) : Favo
|
||||
override suspend fun deleteItem(item: Favourite) {
|
||||
favouriteDao.delete(item)
|
||||
}
|
||||
|
||||
override suspend fun isFavourite(id: Int): Boolean {
|
||||
return favouriteDao.isFavourite(id)
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
@ -30,7 +31,6 @@ import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.ti.mobpo.ui.pokesearch.PokeSearchViewModel
|
||||
import com.ti.mobpo.ui.screens.Favourites
|
||||
import com.ti.mobpo.ui.screens.PokeSearchScreen
|
||||
|
||||
@ -61,8 +61,6 @@ fun Navigation() {
|
||||
val updatedSelectedIndex = items.indexOfFirst { it.route == currentRoute }
|
||||
selectedItemIndex = rememberUpdatedState(updatedSelectedIndex).value
|
||||
|
||||
val pokeSearchViewModel: PokeSearchViewModel = viewModel()
|
||||
|
||||
Scaffold (
|
||||
bottomBar = {
|
||||
NavigationBar {
|
||||
@ -106,7 +104,7 @@ fun Navigation() {
|
||||
ExitTransition.None
|
||||
}) {
|
||||
composable(route = Screen.PokeSearch.route) {
|
||||
PokeSearchScreen(pokeSearchViewModel)
|
||||
PokeSearchScreen()
|
||||
}
|
||||
composable(
|
||||
route = Screen.Favourites.route) {
|
||||
@ -124,7 +122,6 @@ fun Navigation() {
|
||||
@Composable
|
||||
fun NavigationPreview() {
|
||||
Surface {
|
||||
val pokeSearchViewModel: PokeSearchViewModel = viewModel()
|
||||
PokeSearchScreen(pokeSearchViewModel)
|
||||
PokeSearchScreen()
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@ package com.ti.mobpo.ui.pokesearch
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.ti.mobpo.data.Favourite
|
||||
import com.ti.mobpo.data.FavouritesRepository
|
||||
import com.ti.mobpo.model.PokemonDetails
|
||||
import com.ti.mobpo.network.PokeApi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@ -12,7 +14,7 @@ import java.io.IOException
|
||||
|
||||
|
||||
|
||||
class PokeSearchViewModel : ViewModel() {
|
||||
class PokeSearchViewModel(private val favouritesRepository: FavouritesRepository) : ViewModel() {
|
||||
private val service = PokeApi.retrofitService;
|
||||
|
||||
private val _pokemonDetails = MutableStateFlow<List<PokemonDetails>?>(null)
|
||||
@ -26,7 +28,8 @@ class PokeSearchViewModel : ViewModel() {
|
||||
val detailsList = mutableListOf<PokemonDetails>()
|
||||
for (pokemonSpecies in filteredList) {
|
||||
val details = service.getPokemonDetails(extractPokemonId(pokemonSpecies.url))
|
||||
detailsList.add(details)
|
||||
val isFavorite = favouritesRepository.isFavourite(details.id)
|
||||
detailsList.add(details.copy(isFavorite = isFavorite))
|
||||
}
|
||||
_pokemonDetails.value = detailsList
|
||||
} catch (e: IOException) {
|
||||
@ -48,5 +51,17 @@ class PokeSearchViewModel : ViewModel() {
|
||||
pokemon
|
||||
}
|
||||
}
|
||||
viewModelScope.launch {
|
||||
if (_pokemonDetails.value != null) {
|
||||
val pokemon = _pokemonDetails.value!!.find { it.id == pokemonId }
|
||||
pokemon?.let {
|
||||
if (it.isFavorite) {
|
||||
favouritesRepository.insertItem(Favourite(it.id, it.name))
|
||||
} else {
|
||||
favouritesRepository.deleteItem(Favourite(it.id, it.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,12 +45,13 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.ti.mobpo.model.PokemonDetails
|
||||
import coil.compose.AsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.ti.mobpo.AppViewModelProvider
|
||||
import com.ti.mobpo.capitalizeFirstLetterAfterHyphens
|
||||
import com.ti.mobpo.ui.theme.MobileSecurityTheme
|
||||
|
||||
@Composable
|
||||
fun PokeSearchScreen(pokeSearchViewModel: PokeSearchViewModel) {
|
||||
PokeSearch(pokeSearchViewModel)
|
||||
fun PokeSearchScreen(viewModel: PokeSearchViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
|
||||
PokeSearch(viewModel)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
Loading…
x
Reference in New Issue
Block a user