Replace Dagger2 with Injekt, reorganize dependencies

This commit is contained in:
len 2016-06-14 15:13:48 +02:00
parent 589160242e
commit 21ba371a32
8 changed files with 67 additions and 316 deletions

View File

@ -84,27 +84,22 @@ android {
} }
dependencies { dependencies {
final SUPPORT_LIBRARY_VERSION = '23.4.0'
final DAGGER_VERSION = '2.4'
final RETROFIT_VERSION = '2.0.2'
final NUCLEUS_VERSION = '3.0.0'
final STORIO_VERSION = '1.8.0'
final MOCKITO_VERSION = '1.10.19'
// Modified dependencies // Modified dependencies
compile 'com.github.inorichi:subsampling-scale-image-view:421fb81' compile 'com.github.inorichi:subsampling-scale-image-view:421fb81'
compile 'com.github.inorichi:ReactiveNetwork:69092ed' compile 'com.github.inorichi:ReactiveNetwork:69092ed'
// Android support library // Android support library
compile "com.android.support:support-v4:$SUPPORT_LIBRARY_VERSION" final support_library_version = '23.4.0'
compile "com.android.support:appcompat-v7:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:support-v4:$support_library_version"
compile "com.android.support:cardview-v7:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:appcompat-v7:$support_library_version"
compile "com.android.support:design:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:cardview-v7:$support_library_version"
compile "com.android.support:recyclerview-v7:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:design:$support_library_version"
compile "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:recyclerview-v7:$support_library_version"
compile "com.android.support:preference-v7:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:support-annotations:$support_library_version"
compile "com.android.support:preference-v14:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:preference-v7:$support_library_version"
compile "com.android.support:customtabs:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:preference-v14:$support_library_version"
compile "com.android.support:customtabs:$support_library_version"
// ReactiveX // ReactiveX
compile 'io.reactivex:rxandroid:1.2.0' compile 'io.reactivex:rxandroid:1.2.0'
@ -115,15 +110,17 @@ dependencies {
compile "com.squareup.okhttp3:okhttp:3.3.1" compile "com.squareup.okhttp3:okhttp:3.3.1"
// REST // REST
compile "com.squareup.retrofit2:retrofit:$RETROFIT_VERSION" final retrofit_version = '2.0.2'
compile "com.squareup.retrofit2:converter-gson:$RETROFIT_VERSION" compile "com.squareup.retrofit2:retrofit:$retrofit_version"
compile "com.squareup.retrofit2:adapter-rxjava:$RETROFIT_VERSION" compile "com.squareup.retrofit2:converter-gson:$retrofit_version"
compile "com.squareup.retrofit2:adapter-rxjava:$retrofit_version"
// IO // IO
compile 'com.squareup.okio:okio:1.8.0' compile 'com.squareup.okio:okio:1.8.0'
// JSON // JSON
compile 'com.google.code.gson:gson:2.6.2' compile 'com.google.code.gson:gson:2.6.2'
compile 'com.github.salomonbrys.kotson:kotson:2.2.1'
// YAML // YAML
compile 'org.yaml:snakeyaml:1.17' compile 'org.yaml:snakeyaml:1.17'
@ -141,18 +138,18 @@ dependencies {
compile 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0' compile 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0'
// Database // Database
compile "com.pushtorefresh.storio:sqlite:$STORIO_VERSION" final storio_version = '1.8.0'
compile "com.pushtorefresh.storio:sqlite-annotations:$STORIO_VERSION" compile "com.pushtorefresh.storio:sqlite:$storio_version"
compile "com.pushtorefresh.storio:sqlite-annotations:$storio_version"
// Model View Presenter // Model View Presenter
compile "info.android15.nucleus:nucleus:$NUCLEUS_VERSION" final nucleus_version = '3.0.0'
compile "info.android15.nucleus:nucleus-support-v4:$NUCLEUS_VERSION" compile "info.android15.nucleus:nucleus:$nucleus_version"
compile "info.android15.nucleus:nucleus-support-v7:$NUCLEUS_VERSION" compile "info.android15.nucleus:nucleus-support-v4:$nucleus_version"
compile "info.android15.nucleus:nucleus-support-v7:$nucleus_version"
// Dependency injection // Dependency injection
compile "com.google.dagger:dagger:$DAGGER_VERSION" compile "uy.kohesive.injekt:injekt-core:1.16.1"
kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
provided 'org.glassfish:javax.annotation:10.0-b28'
// Image library // Image library
compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.github.bumptech.glide:glide:3.7.0'
@ -174,13 +171,12 @@ dependencies {
// Tests // Tests
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
testCompile 'org.assertj:assertj-core:1.7.1' testCompile 'org.assertj:assertj-core:1.7.1'
testCompile "org.mockito:mockito-core:$MOCKITO_VERSION" testCompile "org.mockito:mockito-core:1.10.19"
testCompile('org.robolectric:robolectric:3.0') { testCompile('org.robolectric:robolectric:3.0') {
exclude group: 'commons-logging', module: 'commons-logging' exclude group: 'commons-logging', module: 'commons-logging'
exclude group: 'org.apache.httpcomponents', module: 'httpclient' exclude group: 'org.apache.httpcomponents', module: 'httpclient'
} }
kaptTest "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
} }

View File

@ -3,12 +3,10 @@ package eu.kanade.tachiyomi
import android.app.Application import android.app.Application
import android.content.Context import android.content.Context
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.injection.AppComponentFactory
import eu.kanade.tachiyomi.injection.ComponentReflectionInjector
import eu.kanade.tachiyomi.injection.component.AppComponent
import org.acra.ACRA import org.acra.ACRA
import org.acra.annotation.ReportsCrashes import org.acra.annotation.ReportsCrashes
import timber.log.Timber import timber.log.Timber
import uy.kohesive.injekt.Injekt
@ReportsCrashes( @ReportsCrashes(
formUri = "http://tachiyomi.kanade.eu/crash_report", formUri = "http://tachiyomi.kanade.eu/crash_report",
@ -19,22 +17,13 @@ import timber.log.Timber
) )
open class App : Application() { open class App : Application() {
lateinit var component: AppComponent
private set
lateinit var componentReflection: ComponentReflectionInjector<AppComponent>
private set
var appTheme = 0 var appTheme = 0
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
Injekt.importModule(AppModule(this))
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree()) if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
component = createAppComponent()
componentReflection = ComponentReflectionInjector(AppComponent::class.java, component)
setupTheme() setupTheme()
setupAcra() setupAcra()
} }
@ -43,10 +32,6 @@ open class App : Application() {
appTheme = PreferencesHelper.getTheme(this) appTheme = PreferencesHelper.getTheme(this)
} }
protected open fun createAppComponent(): AppComponent {
return AppComponentFactory.create(this)
}
protected open fun setupAcra() { protected open fun setupAcra() {
ACRA.init(this) ACRA.init(this)
} }

View File

@ -0,0 +1,41 @@
package eu.kanade.tachiyomi
import android.app.Application
import com.google.gson.Gson
import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
import eu.kanade.tachiyomi.data.network.NetworkHelper
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.source.SourceManager
import uy.kohesive.injekt.api.InjektModule
import uy.kohesive.injekt.api.InjektRegistrar
import uy.kohesive.injekt.api.addSingletonFactory
class AppModule(val app: Application) : InjektModule {
override fun InjektRegistrar.registerInjectables() {
addSingletonFactory { PreferencesHelper(app) }
addSingletonFactory { DatabaseHelper(app) }
addSingletonFactory { ChapterCache(app) }
addSingletonFactory { CoverCache(app) }
addSingletonFactory { NetworkHelper(app) }
addSingletonFactory { SourceManager(app) }
addSingletonFactory { DownloadManager(app) }
addSingletonFactory { MangaSyncManager(app) }
addSingletonFactory { Gson() }
}
}

View File

@ -1,16 +0,0 @@
package eu.kanade.tachiyomi.injection;
import eu.kanade.tachiyomi.App;
import eu.kanade.tachiyomi.injection.component.AppComponent;
import eu.kanade.tachiyomi.injection.component.DaggerAppComponent;
import eu.kanade.tachiyomi.injection.module.AppModule;
public class AppComponentFactory {
public static AppComponent create(App app) {
return DaggerAppComponent.builder().appModule(new AppModule(app)).build();
}
}

View File

@ -1,97 +0,0 @@
package eu.kanade.tachiyomi.injection;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
/**
* This class allows to inject into objects through a base class,
* so we don't have to repeat injection code everywhere.
*
* The performance drawback is about 0.013 ms per injection on a very slow device,
* which is negligible in most cases.
*
* Example:
* <pre>{@code
* Component {
* void inject(B b);
* }
*
* class A {
* void onCreate() {
* componentReflectionInjector.inject(this);
* }
* }
*
* class B extends A {
* @Inject MyDependency dependency;
* }
*
* new B().onCreate() // dependency will be injected at this point
*
* class C extends B {
*
* }
*
* new C().onCreate() // dependency will be injected at this point as well
* }</pre>
*
* @param <T> a type of dagger 2 component.
*/
public final class ComponentReflectionInjector<T> {
private static final ConcurrentHashMap<Class<?>, HashMap<Class<?>, Method>> cache = new ConcurrentHashMap<>();
private final Class<T> componentClass;
private final T component;
private final HashMap<Class<?>, Method> methods;
public ComponentReflectionInjector(Class<T> componentClass, T component) {
this.componentClass = componentClass;
this.component = component;
this.methods = getMethods(componentClass);
}
public T getComponent() {
return component;
}
public void inject(Object target) {
Class targetClass = target.getClass();
Method method = methods.get(targetClass);
while (method == null && targetClass != null) {
targetClass = targetClass.getSuperclass();
method = methods.get(targetClass);
}
if (method == null)
throw new RuntimeException(String.format("No %s injecting method exists in %s component", target.getClass(), componentClass));
try {
method.invoke(component, target);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static HashMap<Class<?>, Method> getMethods(Class componentClass) {
HashMap<Class<?>, Method> methods = cache.get(componentClass);
if (methods == null) {
synchronized (cache) {
methods = cache.get(componentClass);
if (methods == null) {
methods = new HashMap<>();
for (Method method : componentClass.getMethods()) {
Class<?>[] params = method.getParameterTypes();
if (params.length == 1)
methods.put(params[0], method);
}
cache.put(componentClass, methods);
}
}
}
return methods;
}
}

View File

@ -1,67 +0,0 @@
package eu.kanade.tachiyomi.injection.component
import android.app.Application
import dagger.Component
import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.glide.AppGlideModule
import eu.kanade.tachiyomi.data.glide.MangaModelLoader
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.mangasync.MangaSyncService
import eu.kanade.tachiyomi.data.mangasync.UpdateMangaSyncService
import eu.kanade.tachiyomi.data.source.Source
import eu.kanade.tachiyomi.data.source.online.OnlineSource
import eu.kanade.tachiyomi.data.updater.UpdateDownloader
import eu.kanade.tachiyomi.injection.module.AppModule
import eu.kanade.tachiyomi.injection.module.DataModule
import eu.kanade.tachiyomi.ui.backup.BackupPresenter
import eu.kanade.tachiyomi.ui.catalogue.CataloguePresenter
import eu.kanade.tachiyomi.ui.category.CategoryPresenter
import eu.kanade.tachiyomi.ui.download.DownloadPresenter
import eu.kanade.tachiyomi.ui.library.LibraryPresenter
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaPresenter
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersPresenter
import eu.kanade.tachiyomi.ui.manga.info.MangaInfoPresenter
import eu.kanade.tachiyomi.ui.manga.myanimelist.MyAnimeListPresenter
import eu.kanade.tachiyomi.ui.reader.ReaderPresenter
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersPresenter
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadPresenter
import eu.kanade.tachiyomi.ui.setting.SettingsActivity
import javax.inject.Singleton
@Singleton
@Component(modules = arrayOf(AppModule::class, DataModule::class))
interface AppComponent {
fun inject(libraryPresenter: LibraryPresenter)
fun inject(mangaPresenter: MangaPresenter)
fun inject(cataloguePresenter: CataloguePresenter)
fun inject(mangaInfoPresenter: MangaInfoPresenter)
fun inject(chaptersPresenter: ChaptersPresenter)
fun inject(readerPresenter: ReaderPresenter)
fun inject(downloadPresenter: DownloadPresenter)
fun inject(myAnimeListPresenter: MyAnimeListPresenter)
fun inject(categoryPresenter: CategoryPresenter)
fun inject(recentChaptersPresenter: RecentChaptersPresenter)
fun inject(recentlyReadPresenter: RecentlyReadPresenter)
fun inject(backupPresenter: BackupPresenter)
fun inject(mainActivity: MainActivity)
fun inject(settingsActivity: SettingsActivity)
fun inject(source: Source)
fun inject(mangaSyncService: MangaSyncService)
fun inject(onlineSource: OnlineSource)
fun inject(libraryUpdateService: LibraryUpdateService)
fun inject(downloadService: DownloadService)
fun inject(updateMangaSyncService: UpdateMangaSyncService)
fun inject(mangaModelLoader: MangaModelLoader)
fun inject(appGlideModule: AppGlideModule)
fun inject(updateDownloader: UpdateDownloader)
fun application(): Application
}

View File

@ -1,21 +0,0 @@
package eu.kanade.tachiyomi.injection.module
import android.app.Application
import dagger.Module
import dagger.Provides
import javax.inject.Singleton
/**
* Provide application-level dependencies. Mainly singleton object that can be injected from
* anywhere in the app.
*/
@Module
class AppModule(private val application: Application) {
@Provides
@Singleton
fun provideApplication(): Application {
return application
}
}

View File

@ -1,70 +0,0 @@
package eu.kanade.tachiyomi.injection.module
import android.app.Application
import dagger.Module
import dagger.Provides
import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
import eu.kanade.tachiyomi.data.network.NetworkHelper
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.source.SourceManager
import javax.inject.Singleton
/**
* Provide dependencies to the DataManager, mainly Helper classes and Retrofit services.
*/
@Module
open class DataModule {
@Provides
@Singleton
fun providePreferencesHelper(app: Application): PreferencesHelper {
return PreferencesHelper(app)
}
@Provides
@Singleton
open fun provideDatabaseHelper(app: Application): DatabaseHelper {
return DatabaseHelper(app)
}
@Provides
@Singleton
fun provideChapterCache(app: Application): ChapterCache {
return ChapterCache(app)
}
@Provides
@Singleton
fun provideCoverCache(app: Application): CoverCache {
return CoverCache(app)
}
@Provides
@Singleton
open fun provideNetworkHelper(app: Application): NetworkHelper {
return NetworkHelper(app)
}
@Provides
@Singleton
open fun provideSourceManager(app: Application): SourceManager {
return SourceManager(app)
}
@Provides
@Singleton
fun provideDownloadManager(app: Application, sourceManager: SourceManager, preferences: PreferencesHelper): DownloadManager {
return DownloadManager(app, sourceManager, preferences)
}
@Provides
@Singleton
fun provideMangaSyncManager(app: Application): MangaSyncManager {
return MangaSyncManager(app)
}
}