app: setup pagination and a viewmodel for posts

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya 2020-09-23 22:06:56 +05:30
parent 5260f454ef
commit e1c9b34bbe
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
4 changed files with 58 additions and 20 deletions

View file

@ -50,11 +50,13 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
dependencies { 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(":data"))
implementation(project(":lobsters-api")) implementation(project(":lobsters-api"))
implementation(project(":model")) implementation(project(":model"))
implementation 'androidx.core:core-ktx:1.5.0-alpha03' 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.appcompat:appcompat:1.3.0-alpha02'
implementation "androidx.compose.foundation:foundation:$compose_version" implementation "androidx.compose.foundation:foundation:$compose_version"
implementation "androidx.compose.foundation:foundation-layout:$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:$compose_version"
implementation "androidx.compose.ui:ui-text-android:$compose_version" implementation "androidx.compose.ui:ui-text-android:$compose_version"
implementation "androidx.compose.ui:ui-unit:$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-runtime-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.ui:ui-tooling:$compose_version" implementation "androidx.ui:ui-tooling:$compose_version"
implementation 'com.google.android.material:material:1.3.0-alpha02' implementation 'com.google.android.material:material:1.3.0-alpha02'
implementation "com.google.dagger:hilt-android:$hilt_version" implementation "com.google.dagger:hilt-android:$hilt_dagger_version"
androidTestImplementation "com.google.dagger:hilt-android-testing:$hilt_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' testImplementation 'junit:junit:4.13'
androidTestImplementation "androidx.ui:ui-test:$compose_version" androidTestImplementation "androidx.ui:ui-test:$compose_version"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.0.10" coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.0.10"

View file

@ -1,47 +1,42 @@
package dev.msfjarvis.lobsters package dev.msfjarvis.lobsters
import android.os.Bundle import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.Text 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.Scaffold
import androidx.compose.material.TopAppBar import androidx.compose.material.TopAppBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Providers import androidx.compose.runtime.Providers
import androidx.compose.runtime.ambientOf 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.platform.setContent
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dev.msfjarvis.lobsters.api.LobstersApi 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.LobstersItem
import dev.msfjarvis.lobsters.ui.LobstersTheme import dev.msfjarvis.lobsters.ui.LobstersTheme
import dev.msfjarvis.lobsters.urllauncher.UrlLauncher import dev.msfjarvis.lobsters.urllauncher.UrlLauncher
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.withContext
import javax.inject.Inject import javax.inject.Inject
val UrlLauncherAmbient = ambientOf<UrlLauncher> { error("Needs to be provided") } val UrlLauncherAmbient = ambientOf<UrlLauncher> { error("Needs to be provided") }
@AndroidEntryPoint @AndroidEntryPoint
@ExperimentalCoroutinesApi
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
@Inject lateinit var urlLauncher: UrlLauncher @Inject lateinit var urlLauncher: UrlLauncher
@Inject lateinit var apiClient: LobstersApi @Inject lateinit var apiClient: LobstersApi
private val viewModel: LobstersViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
Providers(UrlLauncherAmbient provides urlLauncher) { Providers(UrlLauncherAmbient provides urlLauncher) {
LobstersTheme { LobstersTheme {
val posts = mutableStateListOf<LobstersPost>() LobstersApp(viewModel)
lifecycleScope.launchWhenCreated {
withContext(Dispatchers.IO) {
posts.addAll(apiClient.getHottestPosts(1))
}
}
LobstersApp(posts)
} }
} }
} }
@ -49,15 +44,21 @@ class MainActivity : AppCompatActivity() {
} }
@Composable @Composable
@ExperimentalCoroutinesApi
fun LobstersApp( fun LobstersApp(
items: List<LobstersPost>, viewModel: LobstersViewModel
) { ) {
val urlLauncher = UrlLauncherAmbient.current val urlLauncher = UrlLauncherAmbient.current
val state = viewModel.posts.collectAsState()
val lastIndex = state.value.lastIndex
Scaffold( Scaffold(
topBar = { TopAppBar({ Text(text = stringResource(R.string.app_name)) }) }, topBar = { TopAppBar({ Text(text = stringResource(R.string.app_name)) }) },
bodyContent = { bodyContent = {
LazyColumnFor(items) { item -> LazyColumnForIndexed(state.value) { index, item ->
if (lastIndex == index) {
viewModel.getMorePosts()
}
LobstersItem(item) { post -> LobstersItem(item) { post ->
urlLauncher.launch(post.url) urlLauncher.launch(post.url)
} }

View file

@ -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<List<LobstersPost>>(emptyList())
val posts: StateFlow<List<LobstersPost>> get() = _posts
init {
getMorePosts()
}
fun getMorePosts() {
viewModelScope.launch {
_posts.value += lobstersApi.getHottestPosts(apiPage)
apiPage += 1
}
}
}

View file

@ -4,7 +4,8 @@ buildscript {
compose_version = '1.0.0-alpha03' compose_version = '1.0.0-alpha03'
coroutines_version = '1.3.9' coroutines_version = '1.3.9'
dagger_version = '2.29.1' 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' kotlin_version = '1.4.10'
lifecycle_version = '2.3.0-alpha07' lifecycle_version = '2.3.0-alpha07'
moshi_version = '1.9.3' moshi_version = '1.9.3'
@ -17,7 +18,7 @@ buildscript {
dependencies { dependencies {
classpath "com.android.tools.build:gradle:4.2.0-alpha12" classpath "com.android.tools.build:gradle:4.2.0-alpha12"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 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"
} }
} }