1

So I am a bit stuck with how to create the ViewModel and pass it into my composable so that I can use the Data Class models to display on the textView.

Here's the code

MainActivity

private const val TAG = "MainActivity" class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val viewModel: PokemonListViewModel by viewModels() setContent { // val pokemon = viewModel.pokemon.value PokeDexComposeTheme { Surface( modifier = Modifier.fillMaxSize(), color = Color.Cyan) { PokemonListScreen() } } } } } @Composable fun PokemonListScreen(viewModel: PokemonListViewModel){ //Tried this method as well val pokemon by viewModel.pokemonLiveData.observeAsState("") Column( modifier = Modifier .fillMaxSize() .padding(16.dp), verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.CenterHorizontally, ) { ClickableText( text = AnnotatedString(), onClick = {offset -> Log.d(TAG, "PokemonListScreen: clicked") }, ) Divider( Modifier.padding(start = 24.dp, end = 24.dp), color = Color.Black, thickness = 2.dp ) } } @Composable fun PokemonDetails(){ Column( modifier = Modifier .fillMaxSize() .padding(top = 16.dp), verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.CenterHorizontally ) { Text( fontSize = 25.sp, text = "NAME: " ) Text( fontSize = 50.sp, text = "NameModel" ) Divider( modifier = Modifier.padding(start = 24.dp, end = 24.dp), color = Color.Black, thickness = 1.dp ) Text( modifier = Modifier.padding(8.dp), fontSize = 25.sp, text = "HEIGHT: " ) Text( fontSize = 50.sp, text = "HeightModel" ) Divider( modifier = Modifier.padding(start = 24.dp, end = 24.dp), color = Color.Black, thickness = 1.dp ) Text( modifier = Modifier.padding(8.dp), fontSize = 25.sp, text = "WEIGHT: " ) Text( fontSize = 50.sp, text = "WeightModel" ) Divider( modifier = Modifier.padding(start = 24.dp, end = 24.dp), color = Color.Black, thickness = 1.dp ) } } 

ViewModel

class PokemonListViewModel: ViewModel() { private val repository = PokemonRepository(PokemonApplication.pokemonListDatabase.pokemonDao) init { fetchPokemonNames() } private fun fetchPokemonNames(){ viewModelScope.launch { val fetchPokeListEntity = repository.getAllPokemonNames() pokemon.value = fetchPokeListEntity } } } 

I am pretty new to Jetpack Compose, so my mindset was applying the viewModels the same way I would with regular XML layouts. Any help will be appreciated.

2
  • 2
    What specifically isn't working? Commented Mar 30, 2022 at 22:56
  • I can't seem to connect the viewModel to the Composable, so that I can access the Data Class and populate the TextView. Commented Apr 1, 2022 at 0:54

1 Answer 1

3

So I picked up some courses on Udemy, and StateFlow was the method used to replace MutableLiveData.

class PokemonListViewModel: ViewModel() { private val repository = PokemonRepository(PokemonApplication.pokemonListDatabase.pokemonDao) private val _pokemonStateData = MutableStateFlow<List<PokeListEntity>?>(emptyList()) val pokemonStateData = _pokemonStateData.asStateFlow() init { fetchPokemonNames() } fun fetchPokemonNames(){ viewModelScope.launch { val fetchPokeListEntity = repository.getAllPokemonNames() _pokemonStateData.value = fetchPokeListEntity } } } 

All I had to do was to use StateFlow and set up the ViewModel inside the Composeable properly. And it ended up working perfectly.

@Composable fun PokemonListPage( pokemonViewModel: PokemonListViewModel = viewModel(), //<- adding viewModel as a parameter navController: NavController){ val pokeList = pokemonViewModel.pokemonStateData.collectAsState().value //<- creating a variable for the StateFlow variable Surface( modifier = Modifier .fillMaxHeight() .fillMaxWidth(), ) { Scaffold(topBar = { TopAppBar( backgroundColor = Color.DarkGray, elevation = 0.dp, ) { Row(modifier = Modifier .fillMaxWidth(), horizontalArrangement = Arrangement.Center ){ Text( text = "POKEDEX", fontWeight = FontWeight.Bold, fontSize = 25.sp, color = Color.Magenta ) } } }, backgroundColor = Color.DarkGray){ PokemonCards(pokemons = pokeList!!, navController = navController) //<- setting that variable to another composable which is leveraging the info from the viewModel } 

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

hello, i am facing the same issue here. how do you pass the viewmodel information to the compose? could you please share that
Sorry for the late reply. There's two ways you can go about this. Either you use LiveData and upload the dependency to allow LiveData to be used in Compose or You use StateFlow (highly recommended). StateFlow is the better version of LiveData and is actually meant for Compose. Simply set up StateFlow like you would with LiveData, then on the compose that is using the viewModel, have the viewmodel as a parameter and set it to a variable. Then use that variable and connect it to where you need to connect it. I'll leave some code of the Main Composable up for you to see how it works

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.