Last active
April 26, 2024 16:15
-
-
Save necatisozer/8ba4c614f31f2bcc2e4cf8b945d74c8a to your computer and use it in GitHub Desktop.
Movie App
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import androidx.compose.foundation.layout.Arrangement | |
import androidx.compose.foundation.layout.Column | |
import androidx.compose.foundation.layout.PaddingValues | |
import androidx.compose.foundation.layout.aspectRatio | |
import androidx.compose.foundation.layout.fillMaxSize | |
import androidx.compose.foundation.layout.fillMaxWidth | |
import androidx.compose.foundation.lazy.grid.GridCells | |
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid | |
import androidx.compose.foundation.lazy.grid.items | |
import androidx.compose.foundation.shape.RoundedCornerShape | |
import androidx.compose.material.MaterialTheme | |
import androidx.compose.material.Text | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.LaunchedEffect | |
import androidx.compose.runtime.collectAsState | |
import androidx.compose.runtime.getValue | |
import androidx.compose.ui.Alignment | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.draw.clip | |
import androidx.compose.ui.text.style.TextAlign | |
import androidx.compose.ui.unit.dp | |
import androidx.lifecycle.viewmodel.compose.viewModel | |
import androidx.navigation.compose.NavHost | |
import androidx.navigation.compose.composable | |
import androidx.navigation.compose.rememberNavController | |
import coil3.compose.AsyncImage | |
import org.jetbrains.compose.ui.tooling.preview.Preview | |
@Composable | |
@Preview | |
fun App() { | |
MaterialTheme { | |
val navController = rememberNavController() | |
NavHost(navController, "movies") { | |
composable("movies") { | |
val viewModel = viewModel { MoviesViewModel() } | |
val uiState by viewModel.uiState.collectAsState() | |
LaunchedEffect(viewModel) { | |
viewModel.updateMovies() | |
} | |
MoviesScreen(uiState) | |
} | |
} | |
} | |
} | |
@Composable | |
private fun MoviesScreen(uiState: MoviesUiState, modifier: Modifier = Modifier) { | |
LazyVerticalGrid( | |
columns = GridCells.Adaptive(180.dp), | |
contentPadding = PaddingValues(8.dp), | |
verticalArrangement = Arrangement.spacedBy(8.dp), | |
horizontalArrangement = Arrangement.spacedBy(8.dp), | |
modifier = modifier.fillMaxSize() | |
) { | |
items(uiState.movies) { movie -> | |
MovieCell(movie) | |
} | |
} | |
} | |
@Composable | |
private fun MovieCell(movie: Movie, modifier: Modifier = Modifier) { | |
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier) { | |
AsyncImage( | |
movie.poster, | |
contentDescription = movie.title, | |
modifier = Modifier.fillMaxWidth().aspectRatio(2 / 3f).clip(RoundedCornerShape(16.dp)) | |
) | |
Text(movie.title, textAlign = TextAlign.Center, style = MaterialTheme.typography.h6) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
plugins { | |
alias(libs.plugins.kotlinxSerialization) | |
} | |
kotlin { | |
sourceSets { | |
androidMain.dependencies { | |
implementation(libs.ktor.client.okhttp) | |
} | |
commonMain.dependencies { | |
implementation(libs.ktor.client.core) | |
implementation(libs.ktor.client.content.negotiation) | |
implementation(libs.ktor.serialization.kotlinx.json) | |
implementation(libs.androidx.lifecycle.viewmodel.compose) | |
implementation(libs.androidx.navigation.compose) | |
implementation(libs.coil.compose) | |
implementation(libs.coil.network.ktor) | |
} | |
desktopMain.dependencies { | |
implementation(libs.kotlinx.coroutines.swing) | |
implementation(libs.ktor.client.okhttp) | |
} | |
iosMain.dependencies { | |
implementation(libs.ktor.client.darwin) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[versions] | |
compose-plugin = "1.6.10-beta02" | |
kotlinx-coroutines = "1.8.0" | |
ktor = "2.3.8" | |
androidx-lifecycle = "2.8.0-beta01" | |
androidx-navigation = "2.8.0-alpha02" | |
coil = "3.0.0-alpha06" | |
[libraries] | |
kotlinx-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" } | |
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } | |
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" } | |
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" } | |
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" } | |
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" } | |
androidx-lifecycle-viewmodel-compose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" } | |
androidx-navigation-compose = { module = "org.jetbrains.androidx.navigation:navigation-compose", version.ref = "androidx-navigation" } | |
coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" } | |
coil-network-ktor = { module = "io.coil-kt.coil3:coil-network-ktor", version.ref = "coil" } | |
[plugins] | |
kotlinxSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import kotlinx.serialization.Serializable | |
@Serializable | |
data class Movie( | |
val id: Int, | |
val poster: String, | |
val title: String | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import androidx.lifecycle.ViewModel | |
import androidx.lifecycle.viewModelScope | |
import io.ktor.client.* | |
import io.ktor.client.call.* | |
import io.ktor.client.plugins.contentnegotiation.* | |
import io.ktor.client.request.* | |
import io.ktor.serialization.kotlinx.json.* | |
import kotlinx.coroutines.flow.MutableStateFlow | |
import kotlinx.coroutines.flow.asStateFlow | |
import kotlinx.coroutines.flow.update | |
import kotlinx.coroutines.launch | |
class MoviesViewModel : ViewModel() { | |
private val _uiState = MutableStateFlow(MoviesUiState()) | |
val uiState = _uiState.asStateFlow() | |
private val httpClient = HttpClient { | |
install(ContentNegotiation) { | |
json() | |
} | |
} | |
fun updateMovies() { | |
viewModelScope.launch { | |
val movies = fetchMovies() | |
_uiState.update { it.copy(movies = movies) } | |
} | |
} | |
private suspend fun fetchMovies() = httpClient | |
.get("https://my-json-server.typicode.com/necatisozer/movieapi/popular") | |
.body<List<Movie>>() | |
override fun onCleared() { | |
httpClient.close() | |
super.onCleared() | |
} | |
} | |
data class MoviesUiState(val movies: List<Movie> = emptyList()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment