From 4fe7c64e42e0dd96778c392a8c51f464c4259ce8 Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Sun, 13 Nov 2022 13:15:24 +0530 Subject: [PATCH] refactor(android): migrate to Anvil Fixes #261 --- android/build.gradle.kts | 25 +++++++++++-------- .../msfjarvis/claw/android/AppComponent.kt | 23 +++++++++++++++++ .../msfjarvis/claw/android/ClawApplication.kt | 15 +++++------ .../msfjarvis/claw/android/MainActivity.kt | 7 ++++-- .../claw/android/injection/ApiModule.kt | 6 ++--- .../injection/CoroutineDispatcherModule.kt | 6 ++--- .../android/injection/HTMLConverterModule.kt | 6 ++--- .../injection/MetadataExtractorModule.kt | 6 ++--- .../claw/android/injection/OkHttpModule.kt | 9 +++---- .../android/injection/UrlLauncherModule.kt | 9 +++---- .../msfjarvis/claw/android/ui/LobstersApp.kt | 4 +-- .../claw/android/viewmodel/ClawViewModel.kt | 6 ++--- .../android/work/SavedPostUpdaterWorker.kt | 4 +-- build.gradle.kts | 1 - gradle/libs.versions.toml | 7 ------ settings.gradle.kts | 2 ++ 16 files changed, 76 insertions(+), 60 deletions(-) create mode 100644 android/src/main/kotlin/dev/msfjarvis/claw/android/AppComponent.kt diff --git a/android/build.gradle.kts b/android/build.gradle.kts index 1eb7c58d..2dee6ab2 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -6,20 +6,15 @@ */ @file:Suppress("DSL_SCOPE_VIOLATION", "UnstableApiUsage") -import dagger.hilt.android.plugin.HiltExtension - plugins { id("dev.msfjarvis.claw.android-application") id("dev.msfjarvis.claw.rename-artifacts") id("dev.msfjarvis.claw.kotlin-android") + id("dev.msfjarvis.claw.kotlin-kapt") id("dev.msfjarvis.claw.versioning-plugin") - alias(libs.plugins.hilt) - alias(libs.plugins.napt) + alias(libs.plugins.anvil) } -// Hilt's aggregating task fails with NAPT -extensions.getByType().enableAggregatingTask = false - android { namespace = "dev.msfjarvis.claw.android" defaultConfig { applicationId = "dev.msfjarvis.claw.android" } @@ -45,13 +40,17 @@ android { } dependencies { + anvil(libs.tangle.viewmodel.compiler) + anvil(libs.tangle.work.compiler) + kapt(libs.dagger.compiler) implementation(platform(libs.androidx.compose.bom)) - annotationProcessor(libs.androidx.hilt.compiler) - annotationProcessor(libs.dagger.hilt.compiler) + implementation(libs.dagger) implementation(projects.api) implementation(projects.common) + implementation(projects.core) implementation(projects.coroutineUtils) implementation(projects.database) + implementation(projects.diScopes) implementation(projects.metadataExtractor) implementation(projects.model) implementation(libs.accompanist.swiperefresh) @@ -59,14 +58,12 @@ dependencies { implementation(libs.androidx.activity.compose) implementation(libs.androidx.compose.material3) implementation(libs.androidx.core.splashscreen) - implementation(libs.androidx.hilt.work) implementation(libs.androidx.lifecycle.compose) implementation(libs.androidx.navigation.compose) implementation(libs.androidx.paging.compose) implementation(libs.androidx.work.runtime.ktx) implementation(libs.coil) implementation(libs.copydown) - implementation(libs.dagger.hilt.android) implementation(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.serialization.json) implementation(libs.material.motion.core) @@ -74,4 +71,10 @@ dependencies { implementation(libs.okhttp.loggingInterceptor) implementation(libs.retrofit.kotlinxSerializationConverter) implementation(libs.sqldelight.extensions.coroutines) + implementation(libs.tangle.viewmodel.api) + implementation(libs.tangle.viewmodel.compose) { + // https://github.com/RBusarow/Tangle/issues/558 + exclude("androidx.compose.compiler") + } + implementation(libs.tangle.work.api) } diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/AppComponent.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/AppComponent.kt new file mode 100644 index 00000000..01ceb1f3 --- /dev/null +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/AppComponent.kt @@ -0,0 +1,23 @@ +/* + * Copyright © 2022 Harsh Shandilya. + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + */ +package dev.msfjarvis.claw.android + +import android.app.Application +import com.squareup.anvil.annotations.MergeComponent +import dagger.BindsInstance +import dagger.Component +import dev.msfjarvis.claw.injection.scopes.AppScope +import javax.inject.Singleton + +@Singleton +@MergeComponent(AppScope::class) +interface AppComponent { + @Component.Factory + interface Factory { + fun create(@BindsInstance application: Application): AppComponent + } +} diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/ClawApplication.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/ClawApplication.kt index 572cae63..64b2fcb8 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/ClawApplication.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/ClawApplication.kt @@ -9,33 +9,30 @@ package dev.msfjarvis.claw.android import android.app.Application import android.os.StrictMode import android.util.Log -import androidx.hilt.work.HiltWorkerFactory import androidx.work.Configuration import coil.ImageLoader import coil.ImageLoaderFactory import coil.disk.DiskCache import coil.memory.MemoryCache -import dagger.hilt.android.HiltAndroidApp +import dev.msfjarvis.claw.injection.Components import io.github.aakira.napier.DebugAntilog import io.github.aakira.napier.Napier -import javax.inject.Inject +import tangle.inject.TangleGraph -@HiltAndroidApp class ClawApplication : Application(), Configuration.Provider, ImageLoaderFactory { - @Inject lateinit var workerFactory: HiltWorkerFactory override fun onCreate() { super.onCreate() + val component = DaggerAppComponent.factory().create(this) + Components.add(component) + TangleGraph.add(component) StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build()) StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()) Napier.base(DebugAntilog()) } override fun getWorkManagerConfiguration(): Configuration { - return Configuration.Builder() - .setMinimumLoggingLevel(Log.DEBUG) - .setWorkerFactory(workerFactory) - .build() + return Configuration.Builder().setMinimumLoggingLevel(Log.DEBUG).build() } override fun newImageLoader(): ImageLoader { diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/MainActivity.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/MainActivity.kt index c50e33fc..2e5d52c4 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/MainActivity.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/MainActivity.kt @@ -17,15 +17,17 @@ import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.NetworkType import androidx.work.PeriodicWorkRequestBuilder import androidx.work.WorkManager -import dagger.hilt.android.AndroidEntryPoint import dev.msfjarvis.claw.android.ui.LobstersApp import dev.msfjarvis.claw.android.work.SavedPostUpdaterWorker import dev.msfjarvis.claw.common.comments.HTMLConverter import dev.msfjarvis.claw.common.urllauncher.UrlLauncher +import dev.msfjarvis.claw.injection.scopes.AppScope import java.util.concurrent.TimeUnit import javax.inject.Inject +import tangle.inject.TangleGraph +import tangle.inject.TangleScope -@AndroidEntryPoint +@TangleScope(AppScope::class) class MainActivity : ComponentActivity() { @Inject lateinit var urlLauncher: UrlLauncher @@ -34,6 +36,7 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + TangleGraph.inject(this) installSplashScreen() setContent { LobstersApp( diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/ApiModule.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/ApiModule.kt index 8d36b724..9a38dff4 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/ApiModule.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/ApiModule.kt @@ -9,11 +9,11 @@ package dev.msfjarvis.claw.android.injection import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import com.slack.eithernet.ApiResultCallAdapterFactory import com.slack.eithernet.ApiResultConverterFactory +import com.squareup.anvil.annotations.ContributesTo import dagger.Module import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent import dev.msfjarvis.claw.api.LobstersApi +import dev.msfjarvis.claw.injection.scopes.AppScope import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.json.Json import okhttp3.MediaType.Companion.toMediaType @@ -23,7 +23,7 @@ import retrofit2.create @OptIn(ExperimentalSerializationApi::class) @Module -@InstallIn(SingletonComponent::class) +@ContributesTo(AppScope::class) object ApiModule { @Provides fun provideRetrofit( diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/CoroutineDispatcherModule.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/CoroutineDispatcherModule.kt index 53290067..edb67cce 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/CoroutineDispatcherModule.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/CoroutineDispatcherModule.kt @@ -6,17 +6,17 @@ */ package dev.msfjarvis.claw.android.injection +import com.squareup.anvil.annotations.ContributesTo import dagger.Binds import dagger.Module import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent +import dev.msfjarvis.claw.injection.scopes.AppScope import dev.msfjarvis.claw.util.coroutines.DefaultDispatcherProvider import dev.msfjarvis.claw.util.coroutines.DispatcherProvider import kotlinx.coroutines.CoroutineDispatcher @Module -@InstallIn(SingletonComponent::class) +@ContributesTo(AppScope::class) interface CoroutineDispatcherModule { @Binds fun DefaultDispatcherProvider.bind(): DispatcherProvider diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/HTMLConverterModule.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/HTMLConverterModule.kt index 527d5583..d7cf9c82 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/HTMLConverterModule.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/HTMLConverterModule.kt @@ -6,15 +6,15 @@ */ package dev.msfjarvis.claw.android.injection +import com.squareup.anvil.annotations.ContributesTo import dagger.Module import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent import dev.msfjarvis.claw.common.comments.HTMLConverter +import dev.msfjarvis.claw.injection.scopes.AppScope import io.github.furstenheim.CopyDown @Module -@InstallIn(SingletonComponent::class) +@ContributesTo(AppScope::class) object HTMLConverterModule { @Provides diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/MetadataExtractorModule.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/MetadataExtractorModule.kt index a467ace0..7dc98c72 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/MetadataExtractorModule.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/MetadataExtractorModule.kt @@ -7,14 +7,14 @@ package dev.msfjarvis.claw.android.injection import com.chimbori.crux.Crux +import com.squareup.anvil.annotations.ContributesTo import dagger.Module import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent +import dev.msfjarvis.claw.injection.scopes.AppScope import okhttp3.OkHttpClient @Module -@InstallIn(SingletonComponent::class) +@ContributesTo(AppScope::class) object MetadataExtractorModule { @Provides fun provideCrux( diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/OkHttpModule.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/OkHttpModule.kt index ceb48858..89a45d04 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/OkHttpModule.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/OkHttpModule.kt @@ -8,16 +8,15 @@ package dev.msfjarvis.claw.android.injection import android.content.Context import android.net.TrafficStats +import com.squareup.anvil.annotations.ContributesTo import dagger.Binds import dagger.Module import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent import dagger.multibindings.IntoSet import dev.msfjarvis.claw.android.network.DelegatingSocketFactory import dev.msfjarvis.claw.android.network.NapierLogger import dev.msfjarvis.claw.android.network.UserAgentInterceptor +import dev.msfjarvis.claw.injection.scopes.AppScope import java.net.Socket import javax.net.SocketFactory import okhttp3.Cache @@ -26,7 +25,7 @@ import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor @Module -@InstallIn(SingletonComponent::class) +@ContributesTo(AppScope::class) interface OkHttpModule { @Binds fun NapierLogger.bindLogger(): HttpLoggingInterceptor.Logger @@ -38,7 +37,7 @@ interface OkHttpModule { private const val THREAD_STATS_TAG = 0x000090000 @Provides - fun provideCache(@ApplicationContext context: Context): Cache { + fun provideCache(context: Context): Cache { return Cache(context.cacheDir, CACHE_SIZE_MB) } diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/UrlLauncherModule.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/UrlLauncherModule.kt index 74f83567..168b8945 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/UrlLauncherModule.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/injection/UrlLauncherModule.kt @@ -7,18 +7,17 @@ package dev.msfjarvis.claw.android.injection import android.content.Context +import com.squareup.anvil.annotations.ContributesTo import dagger.Module import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.components.ActivityComponent -import dagger.hilt.android.qualifiers.ActivityContext import dev.msfjarvis.claw.common.urllauncher.UrlLauncher +import dev.msfjarvis.claw.injection.scopes.AppScope @Module -@InstallIn(ActivityComponent::class) +@ContributesTo(AppScope::class) object UrlLauncherModule { @Provides - fun provideUrlLauncher(@ActivityContext context: Context): UrlLauncher { + fun provideUrlLauncher(context: Context): UrlLauncher { return UrlLauncher(context) } } diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt index 9f266964..aa9a0d2b 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt @@ -27,7 +27,6 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight -import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavType import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.navArgument @@ -54,6 +53,7 @@ import kotlinx.coroutines.launch import soup.compose.material.motion.navigation.MaterialMotionNavHost import soup.compose.material.motion.navigation.composable import soup.compose.material.motion.navigation.rememberMaterialMotionNavController +import tangle.viewmodel.compose.tangleViewModel @Suppress("ModifierMissing") // Top-level composable, will never have a modifier supplied. @OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class) @@ -62,7 +62,7 @@ fun LobstersApp( urlLauncher: UrlLauncher, htmlConverter: HTMLConverter, setWebUri: (String?) -> Unit, - viewModel: ClawViewModel = viewModel(), + viewModel: ClawViewModel = tangleViewModel(), ) { val systemUiController = rememberSystemUiController() val hottestListState = rememberLazyListState() diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/viewmodel/ClawViewModel.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/viewmodel/ClawViewModel.kt index a1077235..1dce61b8 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/viewmodel/ClawViewModel.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/viewmodel/ClawViewModel.kt @@ -12,7 +12,6 @@ import androidx.paging.Pager import androidx.paging.PagingConfig import com.slack.eithernet.ApiResult.Failure import com.slack.eithernet.ApiResult.Success -import dagger.hilt.android.lifecycle.HiltViewModel import dev.msfjarvis.claw.android.injection.IODispatcher import dev.msfjarvis.claw.android.paging.LobstersPagingSource import dev.msfjarvis.claw.android.ui.toLocalDateTime @@ -20,16 +19,15 @@ import dev.msfjarvis.claw.api.LobstersApi import dev.msfjarvis.claw.database.local.SavedPost import java.io.IOException import java.time.Month -import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import tangle.viewmodel.VMInject -@HiltViewModel class ClawViewModel -@Inject +@VMInject constructor( private val api: LobstersApi, private val savedPostsRepository: SavedPostsRepository, diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/work/SavedPostUpdaterWorker.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/work/SavedPostUpdaterWorker.kt index 77f78aa5..34951c47 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/work/SavedPostUpdaterWorker.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/work/SavedPostUpdaterWorker.kt @@ -7,7 +7,6 @@ package dev.msfjarvis.claw.android.work import android.content.Context -import androidx.hilt.work.HiltWorker import androidx.work.CoroutineWorker import androidx.work.WorkerParameters import com.slack.eithernet.ApiResult @@ -20,6 +19,7 @@ import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.flow.first import kotlinx.coroutines.supervisorScope +import tangle.work.TangleWorker /** * WorkManager-backed [CoroutineWorker] that gets all the posts from [SavedPostsRepository], fetches @@ -27,7 +27,7 @@ import kotlinx.coroutines.supervisorScope * saved posts that were saved before comment counts were added to be able to show a comment count * and for new-enough posts that are still getting comments to have an accurate one. */ -@HiltWorker +@TangleWorker class SavedPostUpdaterWorker @AssistedInject constructor( diff --git a/build.gradle.kts b/build.gradle.kts index 8ba1b769..b004a595 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,6 +10,5 @@ plugins { id("dev.msfjarvis.claw.spotless") id("dev.msfjarvis.claw.versions") id("dev.msfjarvis.claw.kotlin-common") - alias(libs.plugins.hilt) apply false alias(libs.plugins.android.test) apply false } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8ed7ddae..3c40e44d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,6 @@ coil = "2.2.2" composeCompiler = "1.4.0-alpha02" coroutines = "1.6.4" dagger = "2.44.1" -hilt = "1.0.0" kotlin = "1.7.21" material_motion = "0.10.3" # @pin Needs to be aligned with Retrofit @@ -37,8 +36,6 @@ androidx-compose-ui-text = { module = "androidx.compose.ui:ui-text" } androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" } androidx-core-splashscreen = "androidx.core:core-splashscreen:1.0.0" -androidx-hilt-compiler = { module = "androidx.hilt:hilt-compiler", version.ref = "hilt" } -androidx-hilt-work = { module = "androidx.hilt:hilt-work", version.ref = "hilt" } androidx-lifecycle-compose = "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.0-alpha03" androidx-navigation-compose = "androidx.navigation:navigation-compose:2.6.0-alpha04" androidx-paging-compose = "androidx.paging:paging-compose:1.0.0-alpha17" @@ -68,9 +65,6 @@ copydown = "io.github.furstenheim:copy_down:1.1" crux = "com.chimbori.crux:crux:3.11.0" dagger = { module = "com.google.dagger:dagger", version.ref = "dagger" } dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "dagger" } -dagger-hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "dagger" } -dagger-hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "dagger" } -dagger-hilt-core = { module = "com.google.dagger:hilt-core", version.ref = "dagger" } eithernet = "com.slack.eithernet:eithernet:1.2.1" javapoet = "com.squareup:javapoet:1.13.0" javax-inject = "javax.inject:javax.inject:1" @@ -98,7 +92,6 @@ testparameterinjector = "com.google.testparameterinjector:test-parameter-injecto [plugins] android-test = { id = "com.android.test", version.ref = "agp" } -hilt = { id = "com.google.dagger.hilt.android", version.ref = "dagger" } anvil = "com.squareup.anvil:2.4.2" napt = "com.sergei-lapin.napt:1.18" sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } diff --git a/settings.gradle.kts b/settings.gradle.kts index dfddf024..456207b1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -140,8 +140,10 @@ include( "api", "benchmark", "common", + "core", "coroutine-utils", "database", + "di-scopes", "metadata-extractor", "model", )