Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hilt example module #135

Merged
merged 11 commits into from
Feb 17, 2021
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ buildscript {
classpath(kotlin(Deps.Kotlin.gradlePlugin, Versions.kotlin))
classpath(Deps.Plugins.bintray)
classpath(Deps.Plugins.dokka)
classpath(Deps.DI.hiltPlugin)
classpath(Deps.AndroidX.safeArgsPlugin)
}

extra.apply {
Expand Down
14 changes: 14 additions & 0 deletions buildSrc/src/main/kotlin/Deps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,34 @@ object Deps {
const val daggerSupport = "com.google.dagger:dagger-android-support:${Versions.dagger}"
const val daggerProcessor = "com.google.dagger:dagger-android-processor:${Versions.dagger}"
const val daggerCompiler = "com.google.dagger:dagger-compiler:${Versions.dagger}"
const val hiltPlugin = "com.google.dagger:hilt-android-gradle-plugin:${Versions.hilt}"
const val hilt = "com.google.dagger:hilt-android:${Versions.hilt}"
const val hiltCompiler = "com.google.dagger:hilt-android-compiler:${Versions.hilt}"
const val hiltViewModel = "androidx.hilt:hilt-lifecycle-viewmodel:${Versions.hiltJetpack}"
const val hiltNavigationFrag = "androidx.hilt:hilt-navigation-fragment:${Versions.hiltJetpack}"
const val hiltNavigation = "androidx.hilt:hilt-navigation:${Versions.hiltJetpack}"
const val hiltJetpackCompiler = "androidx.hilt:hilt-compiler:${Versions.hiltJetpack}"
}

object AndroidX {
const val appcompat = "androidx.appcompat:appcompat:${Versions.androidx}"
const val annnotation = "androidx.annotation:annotation:${Versions.androidxAnnotation}"
const val multidex = "androidx.multidex:multidex:${Versions.multidex}"
const val material = "com.google.android.material:material:${Versions.material}"
const val vectorDrawable = "androidx.vectordrawable:vectordrawable:${Versions.vectorDrawable}"
const val constraintLayout = "androidx.constraintlayout:constraintlayout:${Versions.constraintLayout}"

const val lifecycleExtensions = "androidx.lifecycle:lifecycle-extensions:${Versions.lifeCycle}"
const val lifecycleCompiler = "androidx.lifecycle:lifecycle-compiler:${Versions.lifeCycle}"
const val liveDataExtensions = "androidx.lifecycle:lifecycle-livedata-ktx:${Versions.lifeCycle}"
const val viewModelExtensions = "androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.lifeCycle}"

const val navigationFragment = "androidx.navigation:navigation-fragment-ktx:${Versions.navigation}"
const val navigationUi = "androidx.navigation:navigation-ui-ktx:${Versions.navigation}"
const val safeArgsPlugin = "androidx.navigation:navigation-safe-args-gradle-plugin:${Versions.navigation}"

const val archTesting = "androidx.arch.core:core-testing:${Versions.test}"
const val core = "androidx.core:core-ktx:${Versions.core}"
const val fragment = "androidx.fragment:fragment:${Versions.androidxFragment}"
}

Expand Down
8 changes: 7 additions & 1 deletion buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,19 @@ object Versions {
// core
const val androidx = "1.2.0"
const val androidxAnnotation = "1.1.0"
const val multidex = "2.0.1"
const val core = "1.3.2"
const val androidxFragment = "1.2.5"
const val material = "1.2.1"
const val test = "2.1.0"
const val vectorDrawable = "1.1.0"
const val constraintLayout = "2.0.3"
const val lifeCycle = "2.2.0"
const val dagger = "2.29.1"
const val dagger = "2.32"
const val hilt = "2.31.1-alpha"
const val hiltJetpack = "1.0.0-alpha03"
const val androidXEspresso = "3.3.0"
const val navigation = "2.3.3"

// rx
const val rxKotlin = "2.4.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,13 @@ class UiData<T : Any>(initValue: T) : MutableLiveData<T>() {
super.postValue(value)
}

fun <R : Any> map(mapper: (T) -> R): NonNullLiveData<R> {
val nonNullLiveData = NonNullLiveData(mapper(this.value))
fun <R : Any> map(mapper: (T) -> R): UiDataMediator<R> {
val mediator = UiDataMediator(mapper(this.value))
mediator.addSource(this) {
it?.let {
nonNullLiveData.value = mapper(it)
mediator.value = mapper(it)
}
}
return nonNullLiveData
return mediator
}
}
1 change: 1 addition & 0 deletions example-hilt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
70 changes: 70 additions & 0 deletions example-hilt/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion

plugins {
id("com.android.application")
id("kotlin-android")
id("kotlin-android-extensions")
id("kotlin-kapt")
id("dagger.hilt.android.plugin")
id("androidx.navigation.safeargs.kotlin")
}

android {
compileSdkVersion(ProjectSettings.compileSdk)

defaultConfig {
applicationId = ProjectSettings.applicationId + ".hilt"
minSdkVersion(ProjectSettings.minSdk)
targetSdkVersion(ProjectSettings.targetSdk)
multiDexEnabled = true
}

dataBinding {
isEnabled = true
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = "1.8"
}
}

dependencies {
implementation(project(":core"))
implementation(project(":cr-usecases"))
implementation(project(":bindingadapters"))

implementation(kotlin(Deps.Kotlin.stdlib, KotlinCompilerVersion.VERSION))
implementation(kotlin(Deps.Kotlin.reflect, KotlinCompilerVersion.VERSION))
implementation(Deps.Kotlin.coroutines)

implementation(Deps.AndroidX.appcompat)
implementation(Deps.AndroidX.annnotation)
implementation(Deps.AndroidX.multidex)
implementation(Deps.AndroidX.core)
implementation(Deps.AndroidX.fragment)
implementation(Deps.AndroidX.navigationFragment)
implementation(Deps.AndroidX.navigationUi)
implementation(Deps.AndroidX.constraintLayout)

implementation(Deps.Rx.rxKotlin)
implementation(Deps.Rx.rxAndroid)
implementation(Deps.Rx.rxJava)
implementation(Deps.Rx.rxRelay)
implementation(Deps.Rx.rxDebug)

implementation(Deps.AndroidX.lifecycleExtensions)
implementation(Deps.AndroidX.liveDataExtensions)
kapt(Deps.AndroidX.lifecycleCompiler)

implementation(Deps.DI.hilt)
kapt(Deps.DI.hiltCompiler)
implementation(Deps.DI.hiltViewModel)
implementation(Deps.DI.hiltNavigationFrag)
implementation(Deps.DI.hiltNavigation)
kapt(Deps.DI.hiltJetpackCompiler)
}
21 changes: 21 additions & 0 deletions example-hilt/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
23 changes: 23 additions & 0 deletions example-hilt/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.futured.arkitekt.sample.hilt">

<application
android:name="app.futured.arkitekt.examplehilt.App"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">

<activity android:name="app.futured.arkitekt.examplehilt.ui.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>

</manifest>
18 changes: 18 additions & 0 deletions example-hilt/src/main/java/app/futured/arkitekt/examplehilt/App.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package app.futured.arkitekt.examplehilt

import android.util.Log
import androidx.multidex.MultiDexApplication
import app.futured.arkitekt.core.error.UseCaseErrorHandler
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class App : MultiDexApplication() {

override fun onCreate() {
super.onCreate()

UseCaseErrorHandler.globalOnErrorLogger = { error ->
Log.d("UseCase error", "$error")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package app.futured.arkitekt.examplehilt.data.store

import javax.inject.Inject
import javax.inject.Singleton
import kotlin.random.Random

@Singleton
class SampleStore @Inject constructor() {

val randomValue: Int by lazy {
Random.nextInt(0, 100)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package app.futured.arkitekt.examplehilt.domain

import app.futured.arkitekt.crusecases.UseCase
import app.futured.arkitekt.examplehilt.data.store.SampleStore
import javax.inject.Inject

class GetRandomNumberUseCase @Inject constructor(
private val sampleStore: SampleStore
) : UseCase<Unit, Int>() {

override suspend fun build(args: Unit) = sampleStore.randomValue
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package app.futured.arkitekt.examplehilt.injection

import android.content.Context
import android.content.res.Resources
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
object ApplicationModule {

@Provides
fun resources(@ApplicationContext context: Context): Resources = context.resources
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package app.futured.arkitekt.examplehilt.tools

import android.util.Log
import androidx.annotation.IdRes
import androidx.fragment.app.Fragment
import androidx.navigation.NavDirections
import androidx.navigation.NavOptions
import androidx.navigation.Navigator
import androidx.navigation.fragment.findNavController
import app.futured.arkitekt.core.fragment.BindingViewModelFragment

fun Fragment.navigateBack() {
hideKeyboard()
findNavController().navigateUp()
}

fun Fragment.navigateBack(@IdRes destinationId: Int, inclusive: Boolean = false) {
hideKeyboard()
findNavController()
.popBackStack(destinationId, inclusive)
}

fun Fragment.navigateTo(navDirections: NavDirections, options: NavOptions? = null) = try {
hideKeyboard()
findNavController().navigate(navDirections, options)
} catch (e: Exception) {
Log.e(this::class.java.simpleName, "navigateTo", e)
}

fun Fragment.navigateTo(navDirections: NavDirections, navigatorExtras: Navigator.Extras) = try {
hideKeyboard()
findNavController().navigate(navDirections, navigatorExtras)
} catch (e: Exception) {
Log.e(this::class.java.simpleName, "navigateTo", e)
}

fun Fragment.hideKeyboard() {
if (this is BindingViewModelFragment<*, *, *>) {
hideKeyboard()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package app.futured.arkitekt.examplehilt.tools

import androidx.lifecycle.SavedStateHandle

fun <T> SavedStateHandle.getOrThrow(key: String): T =
get<T>(key) ?: throw IllegalArgumentException("SavedStateHandle missing argument '$key'")
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package app.futured.arkitekt.examplehilt.ui

import androidx.activity.viewModels
import app.futured.arkitekt.examplehilt.ui.base.BaseHiltActivity
import app.futured.arkitekt.sample.hilt.R
import app.futured.arkitekt.sample.hilt.databinding.ActivityMainBinding
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : BaseHiltActivity<MainViewModel, MainViewState, ActivityMainBinding>(), MainView {

override val layoutResId = R.layout.activity_main

override val viewModel: MainViewModel by viewModels()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package app.futured.arkitekt.examplehilt.ui

import app.futured.arkitekt.core.BaseView

interface MainView : BaseView
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package app.futured.arkitekt.examplehilt.ui

import app.futured.arkitekt.crusecases.BaseCrViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class MainViewModel @Inject constructor(
override val viewState: MainViewState
) : BaseCrViewModel<MainViewState>()
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package app.futured.arkitekt.examplehilt.ui

import app.futured.arkitekt.core.ViewState
import javax.inject.Inject

class MainViewState @Inject constructor() : ViewState
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package app.futured.arkitekt.examplehilt.ui

import android.content.res.Resources
import androidx.lifecycle.ViewModel
import app.futured.arkitekt.core.livedata.UiData
import app.futured.arkitekt.sample.hilt.R
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class NavigationViewModel @Inject constructor(resources: Resources) : ViewModel() {

val graphVariable = UiData("")

val outputMessage = graphVariable.map {
resources.getString(R.string.user_name, it)
}
}
Loading