'How to fill in the TextViews with a field in a Data Class in Jetpack Compose?

So this project that I am involved in has me using Jetpack Compose to create my layouts for the first time. So I am pretty new to this. I have data classes that stored the data in them from an API. ViewModel/LiveData is also in use as well. My question is how do you get the TextView to show the data stored in the data models? Any and all answers are welcomed. Thank You.



Solution 1:[1]

First of all, create a ViewModel for your screen through viewModel(). e.g.

val myViewModel: MyViewModel = viewModel()

or

val myViewModel: MyViewModel = hiltViewModel()

for DaggerHilt. (if you can't access those functions, try adding androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1 for viewModel() and androidx.hilt:hilt-navigation-compose:1.0.0 for hiltViewModel()—be mindful that these versions are likely outdated).

Next, pass or inject your repository or UseCase into the ViewModel's constructor and create a state variable to hold and update your text.

@HiltViewModel
class MyViewModel @Inject constructor(
  private val myRepository: MyRepository
): ViewModel() {

  var text by mutableStateOf("")
    private set

  fun setNewText(newText: String) {
    text = newText
  }

  init {
    viewModelScope.launch { // in case it's a suspend function
      setNewText(myRepository.getDataClass().getText())
    }
  }
}

(for mutableStateOf getter and setter delegation, you need to import androidx.compose.runtime.getValue and androidx.compose.runtime.setValue).

Finally, create the Text in your Composable function, call the ViewModel and use it to update your newly created text.

@Composable
fun MyScreen(myViewModel: MyViewModel = hiltViewModel()) {
  Text(
    text = myViewModel.text,
    modifier = Modifier.fillMaxWidth() // modify it as you wish
  )
}

If that doesn't suit your needs, please provide more details on your situation. Also, I'd recommend you check out the documentation if you have any doubts regarding what I've shown you.

Solution 2:[2]

I don't know where exactly you came across the method that you described, but what you need is state-hoisting.

Basic Principles can be found here. This is how it works.

Let us say you have the variable stored in your viewmodel,

var text by mutableStateOf("Initial Value Here") // Use 'by' to avoid writing '.value' every time

Now, you need to create a method in your viewModel to update this variable -- a method that can be called by any code that wishes to modify this variable.

var text by mutableStateOf("Initial Value Here")
fun updateText(newText: String){
  text = newText
}

Now, in your Composable, create two parameters -- one to get the value and another to set it.

@Composable
fun MyTextView(
 text: Int,
 onTextUpdate: (String) -> Unit // It accepts 'String' and returns 'Unit', like 'void' in java
){

 TextField(
    value = text, //Use the Value Here as a normal value,
    onValueChange = onTextUpdate // Pass this as the updating function
 )

}

At the calling site, pass the viewModel's parameters to connect the state-hoisting node, like so.

setContent{
  val viewmodel = ... //Initialize ViewModel Here
  MyTextField(viewmodel.text, viewmodel::updateText)
}

That is pretty much it. You only need a single variable and modifying that will do all the heavy lifting for you -- no need to handle multiple variables like you mentioned above.

Consider taking the codelabs

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dannly
Solution 2