diff --git a/app/src/main/java/com/nimbl3/di/ViewModelKey.kt b/app/src/main/java/com/nimbl3/di/ViewModelKey.kt new file mode 100644 index 000000000..d66bc3402 --- /dev/null +++ b/app/src/main/java/com/nimbl3/di/ViewModelKey.kt @@ -0,0 +1,11 @@ +package com.nimbl3.di + +import android.arch.lifecycle.ViewModel +import dagger.MapKey +import kotlin.reflect.KClass + +@MustBeDocumented +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +@MapKey +internal annotation class ViewModelKey(val value: KClass) \ No newline at end of file diff --git a/app/src/main/java/com/nimbl3/di/modules/ActivityBuilderModule.kt b/app/src/main/java/com/nimbl3/di/modules/ActivityBuilderModule.kt index d71672ac1..459cc2475 100644 --- a/app/src/main/java/com/nimbl3/di/modules/ActivityBuilderModule.kt +++ b/app/src/main/java/com/nimbl3/di/modules/ActivityBuilderModule.kt @@ -3,10 +3,11 @@ package com.nimbl3.di.modules import dagger.Module import dagger.android.ContributesAndroidInjector import com.nimbl3.MainActivity +import com.nimbl3.ui.main.di.MainActivityModule @Module abstract class ActivityBuilderModule { - @ContributesAndroidInjector + @ContributesAndroidInjector(modules = [MainActivityModule::class]) abstract fun bindMainActivity(): MainActivity } diff --git a/app/src/main/java/com/nimbl3/lib/viewmodel/ViewModelFactory.kt b/app/src/main/java/com/nimbl3/lib/viewmodel/ViewModelFactory.kt new file mode 100644 index 000000000..c4b320f57 --- /dev/null +++ b/app/src/main/java/com/nimbl3/lib/viewmodel/ViewModelFactory.kt @@ -0,0 +1,32 @@ +package com.nimbl3.lib.viewmodel + +import android.arch.lifecycle.ViewModel +import android.arch.lifecycle.ViewModelProvider +import javax.inject.Inject +import javax.inject.Provider + +@Suppress("NestedBlockDepth") +class ViewModelFactory @Inject constructor( + private val creators: Map, @JvmSuppressWildcards Provider>) + : ViewModelProvider.Factory { + + @Suppress("UNCHECKED_CAST") + override fun create(modelClass: Class): T { + var creator: Provider? = creators[modelClass] + if (creator == null) { + for ((key, value) in creators) { + if (modelClass.isAssignableFrom(key)) { + creator = value + break + } + } + } + if (creator == null) throw IllegalArgumentException("Unknown ViewModel class type" + modelClass) + + try { + return creator.get() as T + } catch (e: ClassCastException) { + throw e + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nimbl3/ui/base/BaseActivity.kt b/app/src/main/java/com/nimbl3/ui/base/BaseActivity.kt new file mode 100644 index 000000000..859e1ffa6 --- /dev/null +++ b/app/src/main/java/com/nimbl3/ui/base/BaseActivity.kt @@ -0,0 +1,38 @@ +package com.nimbl3.ui.base + +import android.os.Bundle +import android.support.v4.app.Fragment +import android.support.v7.app.AppCompatActivity +import dagger.android.AndroidInjection +import dagger.android.AndroidInjector +import dagger.android.DispatchingAndroidInjector +import dagger.android.support.HasSupportFragmentInjector +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.disposables.Disposable +import javax.inject.Inject + +abstract class BaseActivity: AppCompatActivity(), HasSupportFragmentInjector { + @Inject + lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector + + private var disposables = CompositeDisposable() + + + override fun onCreate(savedInstanceState: Bundle?) { + AndroidInjection.inject(this) + super.onCreate(savedInstanceState) + } + + override fun supportFragmentInjector(): AndroidInjector { + return this.dispatchingAndroidInjector + } + + protected fun Disposable.bindForDisposable() { + disposables.add(this) + } + + override fun onDestroy() { + super.onDestroy() + disposables.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nimbl3/ui/base/BaseFragment.kt b/app/src/main/java/com/nimbl3/ui/base/BaseFragment.kt new file mode 100644 index 000000000..50f6d1a6c --- /dev/null +++ b/app/src/main/java/com/nimbl3/ui/base/BaseFragment.kt @@ -0,0 +1,36 @@ +package com.nimbl3.ui.base + +import android.os.Bundle +import android.support.v4.app.Fragment +import dagger.android.support.AndroidSupportInjection +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.disposables.Disposable + + +abstract class BaseFragment: Fragment() { + private var disposables = CompositeDisposable() + + override fun onCreate(savedInstanceState: Bundle?) { + AndroidSupportInjection.inject(this) + super.onCreate(savedInstanceState) + } + + override fun onDetach() { + super.onDetach() + disposables.dispose() + } + + override fun onDestroy() { + super.onDestroy() + disposables.dispose() + } + + override fun onDestroyView() { + super.onDestroyView() + disposables.clear() + } + + protected fun Disposable.bindForDisposable() { + disposables.add(this) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nimbl3/ui/base/BaseViewModel.kt b/app/src/main/java/com/nimbl3/ui/base/BaseViewModel.kt new file mode 100644 index 000000000..90833a863 --- /dev/null +++ b/app/src/main/java/com/nimbl3/ui/base/BaseViewModel.kt @@ -0,0 +1,35 @@ +package com.nimbl3.ui.base + +import android.arch.lifecycle.ViewModel +import android.content.Intent +import io.reactivex.Observable +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.disposables.Disposable +import io.reactivex.subjects.PublishSubject + +abstract class BaseViewModel : ViewModel() { + + private val disposables: CompositeDisposable = CompositeDisposable() + private val intent = PublishSubject.create() + + override fun onCleared() { + super.onCleared() + disposables.clear() + } + + protected fun Disposable.bindForDisposable() { + disposables.add(this) + } + + /** + * The intent with its bundle taken over from the Activity + */ + protected fun intent(): Observable = this.intent + + /** + * Emitting the Intent data to the corresponding ViewModel of a View for processing + */ + fun intent(intent: Intent) { + this.intent.onNext(intent) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nimbl3/ui/MainActivity.kt b/app/src/main/java/com/nimbl3/ui/main/MainActivity.kt similarity index 88% rename from app/src/main/java/com/nimbl3/ui/MainActivity.kt rename to app/src/main/java/com/nimbl3/ui/main/MainActivity.kt index b1f6dc679..87c200498 100644 --- a/app/src/main/java/com/nimbl3/ui/MainActivity.kt +++ b/app/src/main/java/com/nimbl3/ui/main/MainActivity.kt @@ -1,6 +1,5 @@ package com.nimbl3 -import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.widget.ImageView import android.widget.TextView @@ -10,14 +9,14 @@ import io.reactivex.android.schedulers.AndroidSchedulers import com.nimbl3.extension.setImageUrl import com.nimbl3.data.service.ApiRepository import com.nimbl3.data.service.response.ExampleResponse +import com.nimbl3.ui.base.BaseActivity import javax.inject.Inject -class MainActivity : AppCompatActivity() { +class MainActivity : BaseActivity() { @Inject lateinit var appRepository: ApiRepository override fun onCreate(savedInstanceState: Bundle?) { - AndroidInjection.inject(this) // If we have baseActivity. we can bring it into the base class. super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) diff --git a/app/src/main/java/com/nimbl3/ui/main/MainViewModel.kt b/app/src/main/java/com/nimbl3/ui/main/MainViewModel.kt new file mode 100644 index 000000000..a503f1e94 --- /dev/null +++ b/app/src/main/java/com/nimbl3/ui/main/MainViewModel.kt @@ -0,0 +1,9 @@ +package com.nimbl3.ui.main + +import com.nimbl3.ui.base.BaseViewModel + +// TODO: remove this rule later! +@Suppress("EmptyClassBlock") +class MainViewModel : BaseViewModel() { + +} \ No newline at end of file diff --git a/app/src/main/java/com/nimbl3/ui/main/di/MainActivityModule.kt b/app/src/main/java/com/nimbl3/ui/main/di/MainActivityModule.kt new file mode 100644 index 000000000..eae6bdc08 --- /dev/null +++ b/app/src/main/java/com/nimbl3/ui/main/di/MainActivityModule.kt @@ -0,0 +1,17 @@ +package com.nimbl3.ui.main.di + +import android.arch.lifecycle.ViewModel +import com.nimbl3.di.ViewModelKey +import com.nimbl3.ui.main.MainViewModel +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap + +@Module +internal abstract class MainActivityModule { + + @Binds + @IntoMap + @ViewModelKey(MainViewModel::class) + abstract fun bindMainViewModel(viewModel: MainViewModel): ViewModel +} \ No newline at end of file