diff --git a/app/build.gradle b/app/build.gradle index f1defb04..f9e3ea34 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -50,11 +50,13 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { dependencies { - kapt "com.google.dagger:hilt-android-compiler:$hilt_version" + kapt "com.google.dagger:hilt-android-compiler:$hilt_dagger_version" + kapt "androidx.hilt:hilt-compiler:$hilt_androidx_version" implementation(project(":data")) implementation(project(":lobsters-api")) implementation(project(":model")) implementation 'androidx.core:core-ktx:1.5.0-alpha03' + implementation 'androidx.activity:activity-ktx:1.2.0-alpha08' implementation 'androidx.appcompat:appcompat:1.3.0-alpha02' implementation "androidx.compose.foundation:foundation:$compose_version" implementation "androidx.compose.foundation:foundation-layout:$compose_version" @@ -66,12 +68,14 @@ dependencies { implementation "androidx.compose.ui:ui-text:$compose_version" implementation "androidx.compose.ui:ui-text-android:$compose_version" implementation "androidx.compose.ui:ui-unit:$compose_version" + implementation "androidx.hilt:hilt-lifecycle-viewmodel:$hilt_androidx_version" implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" implementation "androidx.ui:ui-tooling:$compose_version" implementation 'com.google.android.material:material:1.3.0-alpha02' - implementation "com.google.dagger:hilt-android:$hilt_version" - androidTestImplementation "com.google.dagger:hilt-android-testing:$hilt_version" + implementation "com.google.dagger:hilt-android:$hilt_dagger_version" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" + androidTestImplementation "com.google.dagger:hilt-android-testing:$hilt_dagger_version" testImplementation 'junit:junit:4.13' androidTestImplementation "androidx.ui:ui-test:$compose_version" coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.0.10" diff --git a/app/src/main/java/dev/msfjarvis/lobsters/MainActivity.kt b/app/src/main/java/dev/msfjarvis/lobsters/MainActivity.kt index f2a257de..f1348c0d 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/MainActivity.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/MainActivity.kt @@ -1,47 +1,42 @@ package dev.msfjarvis.lobsters import android.os.Bundle +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.Text -import androidx.compose.foundation.lazy.LazyColumnFor +import androidx.compose.foundation.lazy.LazyColumnForIndexed import androidx.compose.material.Scaffold import androidx.compose.material.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.Providers import androidx.compose.runtime.ambientOf -import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.collectAsState import androidx.compose.ui.platform.setContent import androidx.compose.ui.res.stringResource -import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import dev.msfjarvis.lobsters.api.LobstersApi -import dev.msfjarvis.lobsters.model.LobstersPost +import dev.msfjarvis.lobsters.data.LobstersViewModel import dev.msfjarvis.lobsters.ui.LobstersItem import dev.msfjarvis.lobsters.ui.LobstersTheme import dev.msfjarvis.lobsters.urllauncher.UrlLauncher -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext +import kotlinx.coroutines.ExperimentalCoroutinesApi import javax.inject.Inject val UrlLauncherAmbient = ambientOf { error("Needs to be provided") } @AndroidEntryPoint +@ExperimentalCoroutinesApi class MainActivity : AppCompatActivity() { @Inject lateinit var urlLauncher: UrlLauncher @Inject lateinit var apiClient: LobstersApi + private val viewModel: LobstersViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Providers(UrlLauncherAmbient provides urlLauncher) { LobstersTheme { - val posts = mutableStateListOf() - lifecycleScope.launchWhenCreated { - withContext(Dispatchers.IO) { - posts.addAll(apiClient.getHottestPosts(1)) - } - } - LobstersApp(posts) + LobstersApp(viewModel) } } } @@ -49,15 +44,21 @@ class MainActivity : AppCompatActivity() { } @Composable +@ExperimentalCoroutinesApi fun LobstersApp( - items: List, + viewModel: LobstersViewModel ) { val urlLauncher = UrlLauncherAmbient.current + val state = viewModel.posts.collectAsState() + val lastIndex = state.value.lastIndex Scaffold( topBar = { TopAppBar({ Text(text = stringResource(R.string.app_name)) }) }, bodyContent = { - LazyColumnFor(items) { item -> + LazyColumnForIndexed(state.value) { index, item -> + if (lastIndex == index) { + viewModel.getMorePosts() + } LobstersItem(item) { post -> urlLauncher.launch(post.url) } diff --git a/app/src/main/java/dev/msfjarvis/lobsters/data/LobstersViewModel.kt b/app/src/main/java/dev/msfjarvis/lobsters/data/LobstersViewModel.kt new file mode 100644 index 00000000..12e0039d --- /dev/null +++ b/app/src/main/java/dev/msfjarvis/lobsters/data/LobstersViewModel.kt @@ -0,0 +1,32 @@ +package dev.msfjarvis.lobsters.data + +import androidx.hilt.lifecycle.ViewModelInject +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dev.msfjarvis.lobsters.api.LobstersApi +import dev.msfjarvis.lobsters.model.LobstersPost +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch + + +@ExperimentalCoroutinesApi +class LobstersViewModel @ViewModelInject constructor( + private val lobstersApi: LobstersApi, +) : ViewModel() { + private var apiPage = 1 + private val _posts = MutableStateFlow>(emptyList()) + val posts: StateFlow> get() = _posts + + init { + getMorePosts() + } + + fun getMorePosts() { + viewModelScope.launch { + _posts.value += lobstersApi.getHottestPosts(apiPage) + apiPage += 1 + } + } +} diff --git a/build.gradle b/build.gradle index 72617ef8..a6d55a8d 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,8 @@ buildscript { compose_version = '1.0.0-alpha03' coroutines_version = '1.3.9' dagger_version = '2.29.1' - hilt_version = '2.29-alpha' + hilt_androidx_version = '1.0.0-alpha02' + hilt_dagger_version = '2.29-alpha' kotlin_version = '1.4.10' lifecycle_version = '2.3.0-alpha07' moshi_version = '1.9.3' @@ -17,7 +18,7 @@ buildscript { dependencies { classpath "com.android.tools.build:gradle:4.2.0-alpha12" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" + classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_dagger_version" } }