diff --git a/dependencies.gradle b/dependencies.gradle index a9ee8ed2..c803fd2e 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -20,7 +20,7 @@ ext.versions = [ okhttp : "3.10.0", semver : "1.0.0", twitterSerial : "0.1.6", - koin : "0.9.3", + koin : "1.0.0-beta-3", picasso : "2.71828", junit : "4.12", @@ -57,6 +57,7 @@ ext.other = [ semver : "net.swiftzer.semver:semver:$versions.semver", twitterSerial : "com.twitter.serial:serial:$versions.twitterSerial", koinCore : "org.koin:koin-core:$versions.koin", + koinJava : "org.koin:koin-java:$versions.koin", koinAndroid : "org.koin:koin-android:$versions.koin", picasso : "com.squareup.picasso:picasso:$versions.picasso", ] @@ -73,4 +74,5 @@ ext.testing = [ apacheCodecs : "commons-codec:commons-codec:$versions.apacheCodecs", testRunner : "com.android.support.test:runner:$versions.testRunner", robolectric : "org.robolectric:robolectric:$versions.robolectric", + koinTest : "org.koin:koin-test:$versions.koin" ] diff --git a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/di/SubsonicApiModule.kt b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/di/SubsonicApiModule.kt index 200b6328..f5820cb7 100644 --- a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/di/SubsonicApiModule.kt +++ b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/di/SubsonicApiModule.kt @@ -1,10 +1,10 @@ package org.moire.ultrasonic.api.subsonic.di -import org.koin.dsl.context.Context +import org.koin.dsl.context.ModuleDefinition import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient const val SUBSONIC_API_CLIENT_CONTEXT = "SubsonicApiClientContext" -fun Context.subsonicApiModule() = context(SUBSONIC_API_CLIENT_CONTEXT) { - bean { return@bean SubsonicAPIClient(get(), get()) } +fun ModuleDefinition.subsonicApiModule() = module(SUBSONIC_API_CLIENT_CONTEXT) { + single { SubsonicAPIClient(get(), get()) } } diff --git a/ultrasonic/build.gradle b/ultrasonic/build.gradle index 6697dd4e..e26e6631 100644 --- a/ultrasonic/build.gradle +++ b/ultrasonic/build.gradle @@ -63,6 +63,7 @@ dependencies { implementation other.kotlinStdlib implementation other.koinAndroid + implementation other.koinJava testImplementation other.kotlinReflect testImplementation testing.junit diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SubsonicTabActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SubsonicTabActivity.java index be2783af..9423d117 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SubsonicTabActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SubsonicTabActivity.java @@ -38,15 +38,17 @@ import android.view.View.OnTouchListener; import android.widget.*; import net.simonvt.menudrawer.MenuDrawer; import net.simonvt.menudrawer.Position; +import org.koin.java.standalone.KoinJavaComponent; import org.moire.ultrasonic.R; -import org.moire.ultrasonic.app.UApp; import org.moire.ultrasonic.domain.MusicDirectory; import org.moire.ultrasonic.domain.MusicDirectory.Entry; import org.moire.ultrasonic.domain.PlayerState; import org.moire.ultrasonic.domain.Share; import org.moire.ultrasonic.featureflags.Feature; +import org.moire.ultrasonic.featureflags.FeatureStorage; import org.moire.ultrasonic.service.*; import org.moire.ultrasonic.subsonic.SubsonicImageLoaderProxy; +import org.moire.ultrasonic.subsonic.loader.image.SubsonicImageLoader; import org.moire.ultrasonic.util.*; import java.io.File; @@ -808,12 +810,12 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen Util.getImageLoaderConcurrency(this) ); - boolean isNewImageLoaderEnabled = ((UApp) getApplication()).getFeaturesStorage() + boolean isNewImageLoaderEnabled = KoinJavaComponent.get(FeatureStorage.class) .isFeatureEnabled(Feature.NEW_IMAGE_DOWNLOADER); if (isNewImageLoaderEnabled) { IMAGE_LOADER = new SubsonicImageLoaderProxy( legacyImageLoader, - ((UApp) getApplication()).getSubsonicImageLoader() + KoinJavaComponent.get(SubsonicImageLoader.class) ); } else { IMAGE_LOADER = legacyImageLoader; diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java index 98feabc8..4dc2fe6f 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java @@ -9,10 +9,10 @@ import android.provider.SearchRecentSuggestions; import android.support.annotation.Nullable; import android.util.Log; import android.view.View; +import org.koin.java.standalone.KoinJavaComponent; import org.moire.ultrasonic.R; import org.moire.ultrasonic.activity.ServerSettingsActivity; import org.moire.ultrasonic.activity.SubsonicTabActivity; -import org.moire.ultrasonic.app.UApp; import org.moire.ultrasonic.featureflags.Feature; import org.moire.ultrasonic.featureflags.FeatureStorage; import org.moire.ultrasonic.provider.SearchSuggestionProvider; @@ -175,7 +175,7 @@ public class SettingsFragment extends PreferenceFragment CheckBoxPreference ffImageLoader = (CheckBoxPreference) findPreference( Constants.PREFERENCES_KEY_FF_IMAGE_LOADER); - final FeatureStorage featureStorage = ((UApp) getActivity().getApplication()).getFeaturesStorage(); + final FeatureStorage featureStorage = KoinJavaComponent.get(FeatureStorage.class); if (ffImageLoader != null) { ffImageLoader.setChecked(featureStorage.isFeatureEnabled(Feature.NEW_IMAGE_DOWNLOADER)); ffImageLoader.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/app/UApp.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/app/UApp.kt index 8eb735b6..0f2bdc5f 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/app/UApp.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/app/UApp.kt @@ -1,40 +1,29 @@ package org.moire.ultrasonic.app import android.app.Application -import org.koin.android.ext.android.get import org.koin.android.ext.android.startKoin +import org.moire.ultrasonic.di.DiProperties +import org.moire.ultrasonic.di.appPermanentStorage import org.moire.ultrasonic.di.baseNetworkModule import org.moire.ultrasonic.di.directoriesModule import org.moire.ultrasonic.di.featureFlagsModule import org.moire.ultrasonic.di.musicServiceModule -import org.moire.ultrasonic.featureflags.FeatureStorage -import org.moire.ultrasonic.subsonic.loader.image.SubsonicImageLoader -import org.moire.ultrasonic.util.Util class UApp : Application() { override fun onCreate() { super.onCreate() - val sharedPreferences = Util.getPreferences(this) - startKoin(this, listOf( - directoriesModule, - baseNetworkModule, - featureFlagsModule(this), - musicServiceModule(sharedPreferences, this) - )) - } - - /** - * Temporary method to get subsonic image loader from java code. - */ - fun getSubsonicImageLoader(): SubsonicImageLoader { - return get() - } - - /** - * Temporary method to get features storage. - */ - fun getFeaturesStorage(): FeatureStorage { - return get() + startKoin(this, + listOf( + directoriesModule, + appPermanentStorage, + baseNetworkModule, + featureFlagsModule, + musicServiceModule + ), + extraProperties = mapOf( + DiProperties.APP_CONTEXT to applicationContext + ) + ) } } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/AppPermanentStorageModule.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/AppPermanentStorageModule.kt new file mode 100644 index 00000000..fb9c9fb9 --- /dev/null +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/AppPermanentStorageModule.kt @@ -0,0 +1,10 @@ +package org.moire.ultrasonic.di + +import org.koin.dsl.module.module +import org.moire.ultrasonic.util.Util + +const val SP_NAME = "Default_SP" + +val appPermanentStorage = module { + single(name = SP_NAME) { Util.getPreferences(getProperty(DiProperties.APP_CONTEXT)) } +} diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/BaseNetworkModule.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/BaseNetworkModule.kt index 0455ff53..7bf4ee73 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/BaseNetworkModule.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/BaseNetworkModule.kt @@ -1,11 +1,11 @@ package org.moire.ultrasonic.di import okhttp3.OkHttpClient -import org.koin.dsl.module.applicationContext +import org.koin.dsl.module.module /** * Provides base network dependencies. */ -val baseNetworkModule = applicationContext { - bean { OkHttpClient.Builder().build() } +val baseNetworkModule = module { + single { OkHttpClient.Builder().build() } } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/DiProperties.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/DiProperties.kt new file mode 100644 index 00000000..ac4748be --- /dev/null +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/DiProperties.kt @@ -0,0 +1,5 @@ +package org.moire.ultrasonic.di + +object DiProperties { + const val APP_CONTEXT = "app_context" +} diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/DirectoriesModule.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/DirectoriesModule.kt index ddbe21f0..577568ec 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/DirectoriesModule.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/DirectoriesModule.kt @@ -1,9 +1,9 @@ package org.moire.ultrasonic.di -import org.koin.dsl.module.applicationContext +import org.koin.dsl.module.module import org.moire.ultrasonic.cache.AndroidDirectories import org.moire.ultrasonic.cache.Directories -val directoriesModule = applicationContext { - bean { AndroidDirectories(get()) } bind Directories::class +val directoriesModule = module { + single { AndroidDirectories(get()) } bind Directories::class } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/FeatureFlagsModule.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/FeatureFlagsModule.kt index 81a1b09f..5d8d484b 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/FeatureFlagsModule.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/FeatureFlagsModule.kt @@ -1,11 +1,8 @@ package org.moire.ultrasonic.di -import android.content.Context -import org.koin.dsl.module.applicationContext +import org.koin.dsl.module.module import org.moire.ultrasonic.featureflags.FeatureStorage -fun featureFlagsModule( - context: Context -) = applicationContext { - factory { FeatureStorage(context) } +val featureFlagsModule = module { + factory { FeatureStorage(getProperty(DiProperties.APP_CONTEXT)) } } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt index 7809ff1b..661079a3 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt @@ -1,10 +1,9 @@ @file:JvmName("MusicServiceModule") package org.moire.ultrasonic.di -import android.content.Context import android.content.SharedPreferences import android.util.Log -import org.koin.dsl.module.applicationContext +import org.koin.dsl.module.module import org.moire.ultrasonic.BuildConfig import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions @@ -26,40 +25,38 @@ private const val DEFAULT_SERVER_INSTANCE = 1 private const val UNKNOWN_SERVER_URL = "not-exists" private const val LOG_TAG = "MusicServiceModule" -fun musicServiceModule( - sp: SharedPreferences, - context: Context -) = applicationContext { - context(MUSIC_SERVICE_CONTEXT) { +val musicServiceModule = module(MUSIC_SERVICE_CONTEXT) { subsonicApiModule() - bean(name = "ServerInstance") { - return@bean sp.getInt( + single(name = "ServerInstance") { + return@single get(SP_NAME).getInt( Constants.PREFERENCES_KEY_SERVER_INSTANCE, DEFAULT_SERVER_INSTANCE ) } - bean(name = "ServerID") { + single(name = "ServerID") { val serverInstance = get(name = "ServerInstance") + val sp: SharedPreferences = get(SP_NAME) val serverUrl = sp.getString( Constants.PREFERENCES_KEY_SERVER_URL + serverInstance, null ) - return@bean if (serverUrl == null) { + return@single if (serverUrl == null) { UNKNOWN_SERVER_URL } else { abs("$serverUrl$serverInstance".hashCode()).toString() } } - bean { + single { val serverId = get(name = "ServerID") - return@bean PermanentFileStorage(get(), serverId, BuildConfig.DEBUG) + return@single PermanentFileStorage(get(), serverId, BuildConfig.DEBUG) } - bean { + single { val instance = get(name = "ServerInstance") + val sp: SharedPreferences = get(SP_NAME) val serverUrl = sp.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null) val username = sp.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null) val password = sp.getString(Constants.PREFERENCES_KEY_PASSWORD + instance, null) @@ -77,7 +74,7 @@ fun musicServiceModule( password == null ) { Log.i(LOG_TAG, "Server credentials is not available") - return@bean SubsonicClientConfiguration( + return@single SubsonicClientConfiguration( baseUrl = "http://localhost", username = "", password = "", @@ -90,7 +87,7 @@ fun musicServiceModule( debug = BuildConfig.DEBUG ) } else { - return@bean SubsonicClientConfiguration( + return@single SubsonicClientConfiguration( baseUrl = serverUrl, username = username, password = password, @@ -105,16 +102,15 @@ fun musicServiceModule( } } - bean { return@bean SubsonicAPIClient(get()) } + single { SubsonicAPIClient(get()) } - bean(name = ONLINE_MUSIC_SERVICE) { - return@bean CachedMusicService(RESTMusicService(get(), get())) + single(name = ONLINE_MUSIC_SERVICE) { + CachedMusicService(RESTMusicService(get(), get())) } - bean(name = OFFLINE_MUSIC_SERVICE) { - return@bean OfflineMusicService(get(), get()) + single(name = OFFLINE_MUSIC_SERVICE) { + OfflineMusicService(get(), get()) } - bean { return@bean SubsonicImageLoader(context, get()) } + single { SubsonicImageLoader(getProperty(DiProperties.APP_CONTEXT), get()) } } -} diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MusicServiceFactory.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MusicServiceFactory.kt index 5fbb393e..fa10ec1e 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MusicServiceFactory.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MusicServiceFactory.kt @@ -21,7 +21,7 @@ package org.moire.ultrasonic.service import android.content.Context import org.koin.standalone.KoinComponent import org.koin.standalone.get -import org.koin.standalone.releaseContext +import org.koin.standalone.release import org.moire.ultrasonic.cache.Directories import org.moire.ultrasonic.di.MUSIC_SERVICE_CONTEXT import org.moire.ultrasonic.di.OFFLINE_MUSIC_SERVICE @@ -45,7 +45,7 @@ object MusicServiceFactory : KoinComponent { */ @JvmStatic fun resetMusicService() { - releaseContext(MUSIC_SERVICE_CONTEXT) + release(MUSIC_SERVICE_CONTEXT) } @JvmStatic