Get all pokemon from API

This commit is contained in:
Joren 2024-04-29 15:49:08 +02:00
parent 57cc5c827b
commit e8881a2921
Signed by untrusted user who does not match committer: Joren
GPG Key ID: 280E33DFBC0F1B55
2 changed files with 51 additions and 28 deletions

View File

@ -1,60 +1,68 @@
package com.ti.mobpo.ui package com.ti.mobpo.ui
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import retrofit2.Call import kotlinx.coroutines.launch
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET import retrofit2.http.GET
import java.io.IOException
// Data class to hold Pokemon species information private const val BASE_URL = "https://pokeapi.co/api/v2/";
data class PokemonSpecies( data class PokemonSpecies(
@SerializedName("name") val name: String, @SerializedName("name") val name: String,
@SerializedName("url") val url: String @SerializedName("url") val url: String
) )
// Data class to hold the response from the Pokemon species API
data class PokemonSpeciesResponse( data class PokemonSpeciesResponse(
@SerializedName("results") val results: List<PokemonSpecies> @SerializedName("results") val results: List<PokemonSpecies>
) )
interface PokeApiService { interface PokeApiService {
@GET("pokemon-species/?offset=0&limit=1025") @GET("pokemon-species/?offset=0&limit=1025")
fun getPokemonSpecies(): Call<PokemonSpeciesResponse> suspend fun getPokemonSpecies(): PokemonSpeciesResponse
} }
class PokeSearchViewModel : ViewModel() { class PokeSearchViewModel : ViewModel() {
private val retrofit = Retrofit.Builder() private val retrofit = Retrofit.Builder()
.baseUrl("https://pokeapi.co/api/v2/") .baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create())
.build() .build()
private val service = retrofit.create(PokeApiService::class.java) private val service = retrofit.create(PokeApiService::class.java)
private val _uiState = MutableStateFlow(PokeSearchUiState()) private val _initialPokemonList = MutableStateFlow<List<PokemonSpecies>?>(null)
val uiState: StateFlow<PokeSearchUiState> = _uiState.asStateFlow() private val _filteredPokemonList = MutableStateFlow<List<PokemonSpecies>?>(null)
private var pokemonList: List<PokemonSpecies>? = null val pokemonList: StateFlow<List<PokemonSpecies>?> = _filteredPokemonList.asStateFlow()
init { init {
fetchPokemonSpecies() fetchPokemonSpecies()
} }
private fun fetchPokemonSpecies() { private fun fetchPokemonSpecies() {
service.getPokemonSpecies().enqueue(object : retrofit2.Callback<PokemonSpeciesResponse> { viewModelScope.launch {
override fun onResponse(call: Call<PokemonSpeciesResponse>, response: retrofit2.Response<PokemonSpeciesResponse>) { try {
if (response.isSuccessful) { val response = service.getPokemonSpecies()
val speciesResponse = response.body() _initialPokemonList.value = response.results
pokemonList = speciesResponse?.results _filteredPokemonList.value = response.results
} catch (e: IOException) {
/*TODO*/
}
} }
} }
override fun onFailure(call: Call<PokemonSpeciesResponse>, t: Throwable) { fun search(query: String) {
/*TODO*/ val initialPokemonList = _initialPokemonList.value
if (query.isNotBlank() && initialPokemonList != null) {
val filteredList = initialPokemonList.filter { it.name.contains(query, ignoreCase = true) }
_filteredPokemonList.value = filteredList
} else {
_filteredPokemonList.value = initialPokemonList
} }
})
} }
} }

View File

@ -1,9 +1,13 @@
package com.ti.mobpo.ui.screens package com.ti.mobpo.ui.screens
import com.ti.mobpo.ui.PokeSearchViewModel
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -15,30 +19,41 @@ import androidx.compose.ui.unit.dp
import com.ti.mobpo.R import com.ti.mobpo.R
import com.ti.mobpo.ui.SearchBar import com.ti.mobpo.ui.SearchBar
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.ti.mobpo.ui.PokeSearchViewModel
@Composable @Composable
fun PokeSearchScreen(pokesearchViewModel: PokeSearchViewModel = viewModel()){ fun PokeSearchScreen(pokeSearchViewModel: PokeSearchViewModel = viewModel()) {
val pokesearchUiState by pokesearchViewModel.uiState.collectAsState() PokeSearch(pokeSearchViewModel)
PokeSearch()
} }
@Composable @Composable
fun PokeSearch() { fun PokeSearch(pokeSearchViewModel: PokeSearchViewModel = viewModel()) {
Column ( val searchResults by pokeSearchViewModel.pokemonList.collectAsState()
Column(
verticalArrangement = Arrangement.Top, verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(20.dp) .padding(20.dp)
) { ) {
SearchBar(stringResource(R.string.input_field_label)){ value -> SearchBar(stringResource(R.string.input_field_label)) { value ->
run { pokeSearchViewModel.search(value)
println(value) }
Spacer(modifier = Modifier.height(16.dp))
searchResults?.let { results ->
if (results.isNotEmpty()) {
results.forEach { pokemon ->
Text(text = pokemon.name)
}
} else {
Text("No results found")
} }
} }
} }
} }
@Preview(showBackground = true) @Preview(showBackground = true)
@Composable @Composable
fun PokeSearchApp(){ fun PokeSearchApp(){