Skip to content

Commit

Permalink
added Dagger2, but architecture isn't perfect
Browse files Browse the repository at this point in the history
  • Loading branch information
JaCzekanski committed Jun 24, 2018
1 parent 4546bd6 commit e01afd2
Show file tree
Hide file tree
Showing 44 changed files with 558 additions and 161 deletions.
7 changes: 7 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ dependencies {
implementation 'com.squareup.moshi:moshi:1.6.0'
implementation 'com.github.florent37:viewtooltip:1.1.5'

implementation 'com.google.dagger:dagger:2.16'
implementation 'com.google.dagger:dagger-android:2.16'
implementation 'com.google.dagger:dagger-android-support:2.16'
kapt 'com.google.dagger:dagger-compiler:2.16'
kapt 'com.google.dagger:dagger-android-processor:2.16'
compileOnly 'org.glassfish:javax.annotation:10.0-b28'

testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
Expand Down
17 changes: 10 additions & 7 deletions app/src/main/java/info/czekanski/bet/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import android.content.Intent
import android.os.Bundle
import android.support.v4.app.*
import android.support.v7.app.AppCompatActivity
import android.util.Log
import dagger.android.AndroidInjection
import dagger.android.support.DaggerAppCompatActivity
import info.czekanski.bet.R.id.*
import info.czekanski.bet.domain.bets.BetsFragment
import info.czekanski.bet.domain.home.HomeFragment
import info.czekanski.bet.domain.login.*
import info.czekanski.bet.domain.game.GameFragment
import info.czekanski.bet.domain.home.HomeFragment
import info.czekanski.bet.domain.login.LoginActivity
import info.czekanski.bet.domain.matches.MatchesFragment
import info.czekanski.bet.domain.profile.ProfileFragment
import info.czekanski.bet.misc.*
Expand All @@ -17,12 +19,13 @@ import info.czekanski.bet.user.UserProvider
import io.reactivex.rxkotlin.subscribeBy
import kotlinx.android.synthetic.main.activity_main.*
import timber.log.Timber
import javax.inject.Inject


class MainActivity : AppCompatActivity() {
private val config by lazy { ConfigProvider.instance }
private val userProvider by lazy { UserProvider.instance }
private val preferencesProvider by lazy { PreferencesProvider.getInstance(applicationContext) }
class MainActivity : DaggerAppCompatActivity() {
@Inject lateinit var config: ConfigProvider
@Inject lateinit var userProvider: UserProvider
@Inject lateinit var preferencesProvider: PreferencesProvider

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down
27 changes: 25 additions & 2 deletions app/src/main/java/info/czekanski/bet/MyApplication.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,40 @@
package info.czekanski.bet

import android.app.Application
import dagger.android.AndroidInjector
import dagger.android.support.DaggerApplication
import info.czekanski.bet.di.*
import info.czekanski.bet.di.component.*
import info.czekanski.bet.di.utils.CustomDaggerApplication
import info.czekanski.bet.service.NotificationService
import timber.log.Timber

class MyApplication : Application() {
class MyApplication : CustomDaggerApplication() {
lateinit var component: AppComponent

override fun onCreate() {
super.onCreate()
instance = this

NotificationService.createNotificationChannels(this)

if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
}

override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
val c = DaggerAppComponent
.builder()
.application(this)
.build()
this.component = c

return c
}

companion object {
private var instance: MyApplication? = null

fun get(): MyApplication = instance!!
}
}
31 changes: 31 additions & 0 deletions app/src/main/java/info/czekanski/bet/di/component/AppComponent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package info.czekanski.bet.di.component

import dagger.*
import dagger.android.AndroidInjector
import info.czekanski.bet.MyApplication
import info.czekanski.bet.di.module.*
import info.czekanski.bet.di.module.domain.*
import info.czekanski.bet.di.utils.CustomInjectionModule
import info.czekanski.bet.di.module.view_model.ViewModelModule
import info.czekanski.bet.views.OctagonalImageView
import javax.inject.Singleton

@Component(modules = [
CustomInjectionModule::class,
ContextModule::class,
ServiceModule::class,
ViewModelModule::class,
ActivityModule::class,
FragmentModule::class
])
@Singleton
interface AppComponent : AndroidInjector<MyApplication> {
@Component.Builder
interface Builder {
@BindsInstance
fun application(app: MyApplication): Builder
fun build(): AppComponent
}

fun inject(octagonalImageView: OctagonalImageView)
}
31 changes: 31 additions & 0 deletions app/src/main/java/info/czekanski/bet/di/module/ActivityModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package info.czekanski.bet.di.module

import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
import dagger.*
import dagger.android.ContributesAndroidInjector
import info.czekanski.bet.MainActivity
import info.czekanski.bet.domain.login.LoginActivity
import info.czekanski.bet.network.BetApi
import info.czekanski.bet.receiver.UpdateReceiver
import info.czekanski.bet.service.FirebaseTokenRegistrationService
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.moshi.MoshiConverterFactory
import javax.inject.Singleton

@Module
abstract class ActivityModule {

@ContributesAndroidInjector
abstract fun contributeMainActivity(): MainActivity

@ContributesAndroidInjector
abstract fun contributeLoginActivity(): LoginActivity

@ContributesAndroidInjector
abstract fun contributeUpdateReceiver(): UpdateReceiver

@ContributesAndroidInjector
abstract fun contributeFirebaseTokenRegistrationService(): FirebaseTokenRegistrationService
}
23 changes: 23 additions & 0 deletions app/src/main/java/info/czekanski/bet/di/module/ContextModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package info.czekanski.bet.di.module

import android.app.Application
import android.content.*
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import dagger.*
import info.czekanski.bet.MyApplication
import info.czekanski.bet.network.BetApi
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.moshi.MoshiConverterFactory
import javax.inject.Singleton

@Module
abstract class ContextModule {

@Binds
@Singleton
abstract fun context(app: MyApplication): Context

}
45 changes: 45 additions & 0 deletions app/src/main/java/info/czekanski/bet/di/module/ServiceModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package info.czekanski.bet.di.module

import android.content.*
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import dagger.*
import info.czekanski.bet.network.BetApi
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.moshi.MoshiConverterFactory
import javax.inject.Singleton

@Module
class ServiceModule {
@Provides
@Singleton
fun retrofit(): Retrofit = Retrofit.Builder()
.baseUrl("https://bet.czekanski.info/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(MoshiConverterFactory.create())
.build()

@Provides
@Singleton
fun betApi(retrofit: Retrofit): BetApi =
retrofit.create(BetApi::class.java)


@Provides
@Singleton
fun firestore(): FirebaseFirestore = FirebaseFirestore.getInstance()

@Provides
@Singleton
fun firebaseAuth(): FirebaseAuth = FirebaseAuth.getInstance()

@Provides
@Singleton
fun remoteConfig(): FirebaseRemoteConfig = FirebaseRemoteConfig.getInstance()

@Provides
@Singleton
fun preferences(context: Context): SharedPreferences = context.getSharedPreferences("preferences", Context.MODE_PRIVATE)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package info.czekanski.bet.di.module.domain

import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.czekanski.bet.domain.bets.BetsFragment
import info.czekanski.bet.domain.game.GameFragment
import info.czekanski.bet.domain.home.HomeFragment
import info.czekanski.bet.domain.login.LoginFragment
import info.czekanski.bet.domain.matches.MatchesFragment
import info.czekanski.bet.domain.profile.ProfileFragment

@Module
abstract class FragmentModule {

@ContributesAndroidInjector
abstract fun contributeLoginFragment(): LoginFragment

@ContributesAndroidInjector
abstract fun contributeHomeFragment(): HomeFragment

@ContributesAndroidInjector
abstract fun contributeMatchesFragment(): MatchesFragment

@ContributesAndroidInjector
abstract fun contributeBetsFragment(): BetsFragment

@ContributesAndroidInjector
abstract fun contributeGameFragment(): GameFragment

@ContributesAndroidInjector
abstract fun contributeProfileFragment(): ProfileFragment
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package info.czekanski.bet.di.module.view_model

import android.arch.lifecycle.*
import javax.inject.*

@Singleton
class DiViewModelFactory @Inject constructor(
private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>?>
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
var creator: Provider<ViewModel>? = creators[modelClass]
if (creator == null) {
for (entry in creators.entries) {
if (modelClass.isAssignableFrom(entry.key)) {
creator = entry.value
break
}
}
}
if (creator == null) {
throw IllegalArgumentException("unknown model class $modelClass")
}
try {
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package info.czekanski.bet.di.module.view_model

import android.arch.lifecycle.ViewModel
import dagger.MapKey
import kotlin.reflect.KClass

@MustBeDocumented
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package info.czekanski.bet.di.module.view_model

import android.arch.lifecycle.*
import dagger.*
import dagger.multibindings.IntoMap
import info.czekanski.bet.domain.bets.BetsViewModel
import info.czekanski.bet.domain.game.GameViewModel
import info.czekanski.bet.domain.home.HomeViewModel
import info.czekanski.bet.domain.matches.MatchesViewModel


@Module
abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(HomeViewModel::class)
abstract fun bindHomeViewModel(homeViewModel: HomeViewModel): ViewModel

@Binds
@IntoMap
@ViewModelKey(MatchesViewModel::class)
abstract fun bindMathesViewModel(matchesViewModel: MatchesViewModel): ViewModel

@Binds
@IntoMap
@ViewModelKey(GameViewModel::class)
abstract fun bindGameViewModel(gameViewModel: GameViewModel): ViewModel

@Binds
@IntoMap
@ViewModelKey(BetsViewModel::class)
abstract fun bindBetsViewModel(betsViewModel: BetsViewModel): ViewModel

@Binds
abstract fun bindViewModelFactory(factory: DiViewModelFactory): ViewModelProvider.Factory
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package info.czekanski.bet.di.module.view_model

import dagger.Subcomponent
import info.czekanski.bet.domain.bets.BetsViewModel
import info.czekanski.bet.domain.game.GameViewModel
import info.czekanski.bet.domain.home.HomeViewModel
import info.czekanski.bet.domain.matches.MatchesViewModel

@Subcomponent
interface ViewModelSubComponent {
@Subcomponent.Builder
interface Builder {
fun build(): ViewModelSubComponent
}

fun homeViewModel(): HomeViewModel
fun matchesViewModel(): MatchesViewModel
fun betsViewModel(): BetsViewModel
fun gameViewModel(): GameViewModel
}
20 changes: 20 additions & 0 deletions app/src/main/java/info/czekanski/bet/di/utils/BaseFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package info.czekanski.bet.di.utils

import android.arch.lifecycle.*
import android.content.Context
import android.support.v4.app.Fragment
import dagger.android.support.AndroidSupportInjection
import info.czekanski.bet.di.module.view_model.DiViewModelFactory
import javax.inject.Inject

open class BaseFragment : Fragment() {
@Inject lateinit var viewModelFactory: DiViewModelFactory

override fun onAttach(context: Context?) {
AndroidSupportInjection.inject(this)
super.onAttach(context)
}

inline fun <reified T : ViewModel> viewModel(): T = ViewModelProviders.of(this, viewModelFactory).get(T::class.java)
}

Loading

0 comments on commit e01afd2

Please sign in to comment.