Need a bit of help on why data from viewmodel is not shown in the composable function MainContent. I tried to use MVVM style with coroutine but without DI which I think will be easier but somehow, I could not get it to work.
The viewmodel is working as the log.d is showing the correct data from server but somehow, I could not get it to display in
Text(text = viewModel.posts[it].phrase)
Any help will be greatly appreciated. The github link for this program is in https://github.com/somaria/LearnChnCompose
package com.gamecrawl.learnchncompose
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.ViewModel
import com.gamecrawl.learnchncompose.ui.theme.LearnChnComposeTheme
import io.ktor.client.*
import io.ktor.client.engine.android.*
import io.ktor.client.features.*
import io.ktor.client.features.json.*
import io.ktor.client.features.json.serializer.*
import io.ktor.client.features.logging.*
import io.ktor.client.request.*
import io.ktor.http.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewModel: MainViewModel by viewModels()
setContent {
LearnChnComposeTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
MainContent(viewModel)
}
}
}
}
}
class MainViewModel : ViewModel() {
private var _posts = mutableListOf(Post("12", "test phrase", true))
var posts get() = _posts; set(value) {
_posts = value
}
init {
CoroutineScope(Dispatchers.IO).launch {
_posts = KtorClient.httpClient.get("https://learnchn.herokuapp.com/") {
header("Content-Type", "application/json")
}
Log.d("HomeViewModel", "init: ${_posts[1].phrase}")
Log.d("HomeViewModel", "init: ${_posts[1].id}")
}
}
fun addPost(post: Post) {
CoroutineScope(Dispatchers.IO).launch {
val addedpost: Post = KtorClient.httpClient.post("https://learnchn.herokuapp.com/add") {
header("Content-Type", "application/json")
body = post
}
}
}
}
@Composable
fun MainContent(viewModel: MainViewModel) {
Column {
LazyColumn {
items(viewModel.posts.size) {
Text(text = viewModel.posts[it].phrase)
}
}
Button(onClick = {
viewModel.addPost(Post("test", "adding post 222", true))
}) {
Text(text = "Add Post")
}
}
}
@Serializable
data class Post(
val id: String,
val phrase: String,
val published: Boolean
)
object KtorClient {
val json = Json {
encodeDefaults = true
ignoreUnknownKeys = true
isLenient = true
}
val httpClient = HttpClient(Android) {
install(HttpTimeout) {
socketTimeoutMillis = 200000
requestTimeoutMillis = 200000
connectTimeoutMillis = 200000
}
install(Logging) {
logger = object : Logger {
override fun log(message: String) {
Log.d("TAG", "log: $message")
}
}
}
install(JsonFeature) {
serializer = KotlinxSerializer(json)
}
defaultRequest {
contentType(ContentType.Application.Json)
accept(ContentType.Application.Json)
}
}
}