diff --git a/library/build.gradle b/library/build.gradle index 91b2d9c..3b3f646 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -57,10 +57,9 @@ dependencies { implementation 'com.google.android.gms:play-services-maps:16.1.0' implementation 'com.google.android.libraries.places:places:1.1.0' - // Dagger2 - def dagger2Version = '2.21' - implementation "com.google.dagger:dagger:${dagger2Version}" - kapt "com.google.dagger:dagger-compiler:${dagger2Version}" + // Koin for Android + implementation 'org.koin:koin-android:2.0.0-rc-2' + implementation 'org.koin:koin-android-viewmodel:2.0.0-rc-2' // Rx implementation 'io.reactivex.rxjava2:rxjava:2.2.4' diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/PingPlacePicker.kt b/library/src/main/java/com/rtchagas/pingplacepicker/PingPlacePicker.kt index 5d09c06..ff09120 100644 --- a/library/src/main/java/com/rtchagas/pingplacepicker/PingPlacePicker.kt +++ b/library/src/main/java/com/rtchagas/pingplacepicker/PingPlacePicker.kt @@ -1,12 +1,19 @@ package com.rtchagas.pingplacepicker import android.app.Activity +import android.app.Application import android.content.Intent import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.GoogleApiAvailability import com.google.android.gms.common.GooglePlayServicesNotAvailableException import com.google.android.libraries.places.api.model.Place +import com.rtchagas.pingplacepicker.inject.PingKoinContext +import com.rtchagas.pingplacepicker.inject.repositoryModule +import com.rtchagas.pingplacepicker.inject.viewModelModule import com.rtchagas.pingplacepicker.ui.PlacePickerActivity +import org.koin.android.ext.koin.androidContext +import org.koin.android.ext.koin.androidLogger +import org.koin.dsl.koinApplication class PingPlacePicker private constructor() { @@ -18,7 +25,7 @@ class PingPlacePicker private constructor() { * This key will be used to all nearby requests to Google Places API. */ fun setAndroidApiKey(androidKey: String): IntentBuilder { - PingPlacePicker.androidApiKey = androidKey + androidApiKey = androidKey return this } @@ -26,13 +33,15 @@ class PingPlacePicker private constructor() { * This key will be used to all reverse geolocation request to Google Maps API. */ fun setGeolocationApiKey(geoKey: String): IntentBuilder { - PingPlacePicker.geoLocationApiKey = geoKey + geoLocationApiKey = geoKey return this } @Throws(GooglePlayServicesNotAvailableException::class) fun build(activity: Activity): Intent { + initKoin(activity.application) + val result: Int = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(activity) @@ -43,6 +52,21 @@ class PingPlacePicker private constructor() { intent.setClass(activity, PlacePickerActivity::class.java) return intent } + + /** + * Initializes the Dependency Injection framework by passing + * the current application context. + */ + private fun initKoin(application: Application) { + PingKoinContext.koinApp = koinApplication { + androidLogger() + androidContext(application) + modules( + repositoryModule, + viewModelModule + ) + } + } } companion object { diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/inject/AndroidModule.kt b/library/src/main/java/com/rtchagas/pingplacepicker/inject/AndroidModule.kt deleted file mode 100644 index 8558165..0000000 --- a/library/src/main/java/com/rtchagas/pingplacepicker/inject/AndroidModule.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.rtchagas.pingplacepicker.inject - -import android.app.Application -import android.content.Context -import dagger.Module -import dagger.Provides -import javax.inject.Singleton - - -@Module -class AndroidModule(private val application: Application) { - - @Singleton - @Provides - fun provideContext(): Context { - return application - } -} \ No newline at end of file diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/inject/DaggerInjector.kt b/library/src/main/java/com/rtchagas/pingplacepicker/inject/DaggerInjector.kt deleted file mode 100644 index 55fe62c..0000000 --- a/library/src/main/java/com/rtchagas/pingplacepicker/inject/DaggerInjector.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.rtchagas.pingplacepicker.inject - -import android.app.Application - -class DaggerInjector private constructor() { - - companion object { - - private var injector: PingComponent? = null - - private fun buildComponent(application: Application): PingComponent { - return DaggerPingComponent.builder() - .androidModule(AndroidModule(application)).build() - } - - fun getInjector(application: Application): PingComponent { - return injector ?: buildComponent(application) - } - } -} \ No newline at end of file diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/inject/PingComponent.kt b/library/src/main/java/com/rtchagas/pingplacepicker/inject/PingComponent.kt deleted file mode 100644 index 37b3f62..0000000 --- a/library/src/main/java/com/rtchagas/pingplacepicker/inject/PingComponent.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.rtchagas.pingplacepicker.inject - -import com.rtchagas.pingplacepicker.repository.inject.RepositoryModule -import com.rtchagas.pingplacepicker.ui.PlaceConfirmDialogFragment -import com.rtchagas.pingplacepicker.ui.PlacePickerActivity -import com.rtchagas.pingplacepicker.viewmodel.inject.ViewModelModule -import dagger.Component -import javax.inject.Singleton - -@Singleton -@Component( - modules = [ - AndroidModule::class, - ViewModelModule::class, - RepositoryModule::class - ] -) -interface PingComponent { - - fun inject(activity: PlacePickerActivity) - fun inject(fragment: PlaceConfirmDialogFragment) -} \ No newline at end of file diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/inject/PingKoinComponent.kt b/library/src/main/java/com/rtchagas/pingplacepicker/inject/PingKoinComponent.kt new file mode 100644 index 0000000..c9545c0 --- /dev/null +++ b/library/src/main/java/com/rtchagas/pingplacepicker/inject/PingKoinComponent.kt @@ -0,0 +1,17 @@ +package com.rtchagas.pingplacepicker.inject + +import org.koin.core.Koin +import org.koin.core.KoinApplication +import org.koin.core.KoinComponent + +object PingKoinContext { + + var koinApp: KoinApplication? = null + +} + +interface PingKoinComponent : KoinComponent { + + override fun getKoin(): Koin = PingKoinContext.koinApp?.koin!! + +} \ No newline at end of file diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/repository/inject/RepositoryModule.kt b/library/src/main/java/com/rtchagas/pingplacepicker/inject/RepositoryModule.kt similarity index 56% rename from library/src/main/java/com/rtchagas/pingplacepicker/repository/inject/RepositoryModule.kt rename to library/src/main/java/com/rtchagas/pingplacepicker/inject/RepositoryModule.kt index da40db6..7cefe80 100644 --- a/library/src/main/java/com/rtchagas/pingplacepicker/repository/inject/RepositoryModule.kt +++ b/library/src/main/java/com/rtchagas/pingplacepicker/inject/RepositoryModule.kt @@ -1,42 +1,28 @@ -package com.rtchagas.pingplacepicker.repository.inject +package com.rtchagas.pingplacepicker.inject -import android.content.Context import com.google.android.libraries.places.api.Places -import com.google.android.libraries.places.api.net.PlacesClient import com.rtchagas.pingplacepicker.PingPlacePicker import com.rtchagas.pingplacepicker.repository.PlaceRepository import com.rtchagas.pingplacepicker.repository.googlemaps.GoogleMapsAPI import com.rtchagas.pingplacepicker.repository.googlemaps.GoogleMapsRepository -import dagger.Module -import dagger.Provides import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor +import org.koin.android.ext.koin.androidContext +import org.koin.dsl.module import retrofit2.Retrofit import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory import retrofit2.converter.moshi.MoshiConverterFactory -import javax.inject.Singleton +val repositoryModule = module { -@Module -class RepositoryModule { - - @Singleton - @Provides - fun providePlaceRepository(placesClient: PlacesClient, googleMapsAPI: GoogleMapsAPI) - : PlaceRepository { - return GoogleMapsRepository(placesClient, googleMapsAPI) - } - - @Singleton - @Provides - fun providesGooglePlacesClient(context: Context): PlacesClient { - Places.initialize(context, PingPlacePicker.androidApiKey) - return Places.createClient(context) + // PlacesClient + single { + Places.initialize(androidContext(), PingPlacePicker.androidApiKey) + return@single Places.createClient(androidContext()) } - @Singleton - @Provides - fun provideGoogleMapsAPI(): GoogleMapsAPI { + // GoogleMapsAPI + single(createdAtStart = true) { val interceptor = HttpLoggingInterceptor() interceptor.level = HttpLoggingInterceptor.Level.NONE @@ -50,6 +36,9 @@ class RepositoryModule { .client(client) .build() - return retrofit.create(GoogleMapsAPI::class.java) + return@single retrofit.create(GoogleMapsAPI::class.java) } + + // GoogleMapsRepository + single { GoogleMapsRepository(googleClient = get(), googleMapsAPI = get()) as PlaceRepository } } \ No newline at end of file diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/inject/ViewModelModule.kt b/library/src/main/java/com/rtchagas/pingplacepicker/inject/ViewModelModule.kt new file mode 100644 index 0000000..871bddb --- /dev/null +++ b/library/src/main/java/com/rtchagas/pingplacepicker/inject/ViewModelModule.kt @@ -0,0 +1,14 @@ +package com.rtchagas.pingplacepicker.inject + +import com.rtchagas.pingplacepicker.viewmodel.PlaceConfirmDialogViewModel +import com.rtchagas.pingplacepicker.viewmodel.PlacePickerViewModel +import org.koin.android.viewmodel.dsl.viewModel +import org.koin.dsl.module + +val viewModelModule = module { + + viewModel { PlacePickerViewModel(get()) } + + viewModel { PlaceConfirmDialogViewModel(get()) } + +} \ No newline at end of file diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/repository/googlemaps/GoogleMapsRepository.kt b/library/src/main/java/com/rtchagas/pingplacepicker/repository/googlemaps/GoogleMapsRepository.kt index 2d8deed..305589c 100644 --- a/library/src/main/java/com/rtchagas/pingplacepicker/repository/googlemaps/GoogleMapsRepository.kt +++ b/library/src/main/java/com/rtchagas/pingplacepicker/repository/googlemaps/GoogleMapsRepository.kt @@ -15,10 +15,9 @@ import com.rtchagas.pingplacepicker.PingPlacePicker import com.rtchagas.pingplacepicker.model.GeocodeResult import com.rtchagas.pingplacepicker.repository.PlaceRepository import io.reactivex.Single -import javax.inject.Inject -class GoogleMapsRepository @Inject constructor( +class GoogleMapsRepository constructor( private val googleClient: PlacesClient, private val googleMapsAPI: GoogleMapsAPI) : PlaceRepository { diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/ui/PlaceConfirmDialogFragment.kt b/library/src/main/java/com/rtchagas/pingplacepicker/ui/PlaceConfirmDialogFragment.kt index 422c55d..c5a521c 100644 --- a/library/src/main/java/com/rtchagas/pingplacepicker/ui/PlaceConfirmDialogFragment.kt +++ b/library/src/main/java/com/rtchagas/pingplacepicker/ui/PlaceConfirmDialogFragment.kt @@ -11,22 +11,20 @@ import android.view.ViewGroup import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatDialogFragment import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModelProviders import androidx.transition.TransitionManager import com.google.android.libraries.places.api.model.Place import com.rtchagas.pingplacepicker.Config import com.rtchagas.pingplacepicker.PingPlacePicker import com.rtchagas.pingplacepicker.R -import com.rtchagas.pingplacepicker.inject.DaggerInjector +import com.rtchagas.pingplacepicker.inject.PingKoinComponent import com.rtchagas.pingplacepicker.viewmodel.PlaceConfirmDialogViewModel import com.rtchagas.pingplacepicker.viewmodel.Resource -import com.rtchagas.pingplacepicker.viewmodel.inject.PingViewModelFactory import com.squareup.picasso.Picasso import kotlinx.android.synthetic.main.fragment_dialog_place_confirm.view.* -import javax.inject.Inject +import org.koin.android.viewmodel.ext.android.viewModel -class PlaceConfirmDialogFragment : AppCompatDialogFragment() { +class PlaceConfirmDialogFragment : AppCompatDialogFragment(), PingKoinComponent { companion object { @@ -47,23 +45,13 @@ class PlaceConfirmDialogFragment : AppCompatDialogFragment() { var confirmListener: OnPlaceConfirmedListener? = null - @Inject - lateinit var viewModelFactory: PingViewModelFactory - - private lateinit var viewModel: PlaceConfirmDialogViewModel + private val viewModel: PlaceConfirmDialogViewModel by viewModel() private lateinit var place: Place override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // Inject dependencies - DaggerInjector.getInjector(activity!!.application).inject(this) - - // Initialize the ViewModel for this fragment - viewModel = ViewModelProviders.of(this, viewModelFactory) - .get(PlaceConfirmDialogViewModel::class.java) - // Check mandatory parameters for this fragment if ((arguments == null) || (arguments?.getParcelable(ARG_PLACE) == null)) { throw IllegalArgumentException("You must pass a Place as argument to this fragment") diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/ui/PlacePickerActivity.kt b/library/src/main/java/com/rtchagas/pingplacepicker/ui/PlacePickerActivity.kt index f2ed34a..9ee6ea2 100644 --- a/library/src/main/java/com/rtchagas/pingplacepicker/ui/PlacePickerActivity.kt +++ b/library/src/main/java/com/rtchagas/pingplacepicker/ui/PlacePickerActivity.kt @@ -18,7 +18,6 @@ import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.drawable.DrawableCompat import androidx.core.view.doOnLayout import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationServices @@ -37,16 +36,16 @@ import com.karumi.dexter.listener.single.BasePermissionListener import com.rtchagas.pingplacepicker.PingPlacePicker import com.rtchagas.pingplacepicker.R import com.rtchagas.pingplacepicker.helper.PermissionsHelper -import com.rtchagas.pingplacepicker.inject.DaggerInjector +import com.rtchagas.pingplacepicker.inject.PingKoinComponent import com.rtchagas.pingplacepicker.viewmodel.PlacePickerViewModel import com.rtchagas.pingplacepicker.viewmodel.Resource -import com.rtchagas.pingplacepicker.viewmodel.inject.PingViewModelFactory import kotlinx.android.synthetic.main.activity_place_picker.* import org.jetbrains.anko.toast -import javax.inject.Inject +import org.koin.android.viewmodel.ext.android.viewModel -class PlacePickerActivity : AppCompatActivity(), OnMapReadyCallback, +class PlacePickerActivity : AppCompatActivity(), PingKoinComponent, + OnMapReadyCallback, GoogleMap.OnMarkerClickListener, PlaceConfirmDialogFragment.OnPlaceConfirmedListener { @@ -77,28 +76,18 @@ class PlacePickerActivity : AppCompatActivity(), OnMapReadyCallback, private var placeAdapter: PlacePickerAdapter? = null - private lateinit var fusedLocationProviderClient: FusedLocationProviderClient - - private lateinit var viewModel: PlacePickerViewModel + private val viewModel: PlacePickerViewModel by viewModel() - @Inject - lateinit var viewModelFactory: PingViewModelFactory + private lateinit var fusedLocationProviderClient: FusedLocationProviderClient override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_place_picker) - // Inject dependencies - DaggerInjector.getInjector(application).inject(this) - // Configure the toolbar setSupportActionBar(toolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) - // Initialize the ViewModel for this activity - viewModel = ViewModelProviders.of(this, viewModelFactory) - .get(PlacePickerViewModel::class.java) - // Retrieve location and camera position from saved instance state. lastKnownLocation = savedInstanceState ?.getParcelable(STATE_LOCATION) ?: lastKnownLocation diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/PlaceConfirmDialogViewModel.kt b/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/PlaceConfirmDialogViewModel.kt index 5cee965..399e08e 100644 --- a/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/PlaceConfirmDialogViewModel.kt +++ b/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/PlaceConfirmDialogViewModel.kt @@ -8,9 +8,8 @@ import com.rtchagas.pingplacepicker.repository.PlaceRepository import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers -import javax.inject.Inject -class PlaceConfirmDialogViewModel @Inject constructor(private var repository: PlaceRepository) +class PlaceConfirmDialogViewModel constructor(private var repository: PlaceRepository) : BaseViewModel() { private val placePhotoLiveData: MutableLiveData> = MutableLiveData() diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/PlacePickerViewModel.kt b/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/PlacePickerViewModel.kt index c9ccf98..aa90419 100644 --- a/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/PlacePickerViewModel.kt +++ b/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/PlacePickerViewModel.kt @@ -8,9 +8,8 @@ import com.rtchagas.pingplacepicker.repository.PlaceRepository import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers -import javax.inject.Inject -class PlacePickerViewModel @Inject constructor(private var repository: PlaceRepository) +class PlacePickerViewModel constructor(private var repository: PlaceRepository) : BaseViewModel() { // Keep the place list in this view model state diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/inject/PingViewModelFactory.kt b/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/inject/PingViewModelFactory.kt deleted file mode 100644 index 34fc295..0000000 --- a/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/inject/PingViewModelFactory.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.rtchagas.pingplacepicker.viewmodel.inject - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import javax.inject.Inject -import javax.inject.Provider - -class PingViewModelFactory @Inject constructor( - private val mViewModels: Map, @JvmSuppressWildcards Provider> -) : ViewModelProvider.NewInstanceFactory() { - - @Suppress("UNCHECKED_CAST") - override fun create(modelClass: Class): T { - - var factoryProvider: Provider? = null - - for ((key, value) in mViewModels) { - if (modelClass.isAssignableFrom(key)) { - factoryProvider = value - break - } - } - - factoryProvider?.let { - return it.get() as T - } - - throw IllegalArgumentException("Unknown ViewModel class name: $modelClass") - } -} diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/inject/ViewModelKey.kt b/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/inject/ViewModelKey.kt deleted file mode 100644 index 4d699f6..0000000 --- a/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/inject/ViewModelKey.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.rtchagas.pingplacepicker.viewmodel.inject - -import androidx.lifecycle.ViewModel -import dagger.MapKey -import kotlin.reflect.KClass - -@MapKey -@Target(AnnotationTarget.FUNCTION) -@Retention(AnnotationRetention.RUNTIME) -annotation class ViewModelKey(val value: KClass) diff --git a/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/inject/ViewModelModule.kt b/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/inject/ViewModelModule.kt deleted file mode 100644 index 07e8efd..0000000 --- a/library/src/main/java/com/rtchagas/pingplacepicker/viewmodel/inject/ViewModelModule.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.rtchagas.pingplacepicker.viewmodel.inject - -import androidx.lifecycle.ViewModel -import com.rtchagas.pingplacepicker.viewmodel.PlaceConfirmDialogViewModel -import com.rtchagas.pingplacepicker.viewmodel.PlacePickerViewModel -import dagger.Binds -import dagger.Module -import dagger.multibindings.IntoMap - -@Module -abstract class ViewModelModule { - - @Binds - @IntoMap - @ViewModelKey(PlacePickerViewModel::class) - abstract fun bindPlacePickerViewModel(viewViewModel: PlacePickerViewModel): ViewModel - - @Binds - @IntoMap - @ViewModelKey(PlaceConfirmDialogViewModel::class) - abstract fun bindPlaceConfirmDialogViewModel(viewViewModel: PlaceConfirmDialogViewModel): ViewModel -}