diff --git a/app/src/main/java/keijumt/devandroid/App.kt b/app/src/main/java/keijumt/devandroid/App.kt index 0960faa..b420221 100644 --- a/app/src/main/java/keijumt/devandroid/App.kt +++ b/app/src/main/java/keijumt/devandroid/App.kt @@ -1,9 +1,81 @@ package keijumt.devandroid +import android.app.Activity import android.app.Application +import android.os.Bundle +import android.support.v4.app.Fragment +import android.support.v4.app.FragmentActivity +import android.support.v4.app.FragmentManager +import dagger.android.AndroidInjection +import dagger.android.AndroidInjector +import dagger.android.support.AndroidSupportInjection +import dagger.android.support.DaggerApplication +import dagger.android.support.HasSupportFragmentInjector +import keijumt.devandroid.di.Injectable +import keijumt.devandroid.di.Injector -class App : Application() { +class App : DaggerApplication() { + + companion object { + /** + * Activity に dagger#inject を注入 + * + * @param activity 注入したい Activity instance + */ + private fun handleActivity(activity: Activity) { + if (activity is HasSupportFragmentInjector) { + AndroidInjection.inject(activity) /// Inject!!!! + } + (activity as? FragmentActivity)?.supportFragmentManager?.registerFragmentLifecycleCallbacks( + object : FragmentManager.FragmentLifecycleCallbacks() { + override fun onFragmentCreated(fm: FragmentManager?, f: Fragment?, + savedInstanceState: Bundle?) { + if (f is Injectable) { + AndroidSupportInjection.inject(f) + } + } + }, true) + } + } + override fun onCreate() { super.onCreate() + setupActivityLifecycle() + } + + override fun applicationInjector(): AndroidInjector { + return Injector.setup(this) + } + + /** + * Activity ライフサイクル カスタマイズ + */ + private fun setupActivityLifecycle() { + registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks { + override fun onActivityPaused(activity: Activity?) { + } + + override fun onActivityResumed(activity: Activity?) { + } + + override fun onActivityStarted(activity: Activity?) { + } + + override fun onActivityDestroyed(activity: Activity?) { + } + + override fun onActivitySaveInstanceState(activity: Activity?, bundle: Bundle?) { + } + + override fun onActivityStopped(activity: Activity?) { + } + + override fun onActivityCreated(activity: Activity?, bundle: Bundle?) { + activity?.let { + handleActivity(it) + } + } + + }) } } \ No newline at end of file diff --git a/app/src/main/java/keijumt/devandroid/di/AppComponent.kt b/app/src/main/java/keijumt/devandroid/di/AppComponent.kt new file mode 100644 index 0000000..7a16d2a --- /dev/null +++ b/app/src/main/java/keijumt/devandroid/di/AppComponent.kt @@ -0,0 +1,34 @@ +package keijumt.devandroid.di + +import android.app.Application +import dagger.BindsInstance +import dagger.Component +import dagger.android.AndroidInjector +import dagger.android.support.AndroidSupportInjectionModule +import keijumt.devandroid.App +import keijumt.devandroid.di.module.ActivityModule +import keijumt.devandroid.di.module.AppModule +import javax.inject.Singleton + +@Singleton +@Component(modules = arrayOf( + AndroidSupportInjectionModule::class, + AppModule::class, + ActivityModule::class +)) + +/** + * Component: Application 定義 + */ +interface AppComponent : AndroidInjector { + + @Component.Builder + interface Builder { + @BindsInstance + fun application(application: Application): Builder + + fun build(): AppComponent + } + + override fun inject(application: App) +} \ No newline at end of file diff --git a/app/src/main/java/keijumt/devandroid/di/Injectable.kt b/app/src/main/java/keijumt/devandroid/di/Injectable.kt new file mode 100644 index 0000000..64b0d4b --- /dev/null +++ b/app/src/main/java/keijumt/devandroid/di/Injectable.kt @@ -0,0 +1,7 @@ +package keijumt.devandroid.di + +/** + * Marks an activity / fragment injectable. + * ActivityかFragmentでフィールドインジェクションをしたい場合implementsする + */ +interface Injectable \ No newline at end of file diff --git a/app/src/main/java/keijumt/devandroid/di/Injector.kt b/app/src/main/java/keijumt/devandroid/di/Injector.kt new file mode 100644 index 0000000..ff45a60 --- /dev/null +++ b/app/src/main/java/keijumt/devandroid/di/Injector.kt @@ -0,0 +1,22 @@ +package keijumt.devandroid.di + +import android.app.Application + +/** + * DI Helper + */ +object Injector { + + private lateinit var applicationComponent: AppComponent + + fun setup(application: Application): AppComponent { + applicationComponent = DaggerAppComponent.builder() + .application(application) + .build() + return applicationComponent + } + + fun applicationComponent(): AppComponent { + return applicationComponent + } +} \ No newline at end of file diff --git a/app/src/main/java/keijumt/devandroid/di/module/ActivityModule.kt b/app/src/main/java/keijumt/devandroid/di/module/ActivityModule.kt new file mode 100644 index 0000000..c90e923 --- /dev/null +++ b/app/src/main/java/keijumt/devandroid/di/module/ActivityModule.kt @@ -0,0 +1,11 @@ +package keijumt.devandroid.di.module + +import dagger.Module + +/** + * Module: Activity 定義 + */ +@Module +internal abstract class ActivityModule { + +} \ No newline at end of file diff --git a/app/src/main/java/keijumt/devandroid/di/module/AppModule.kt b/app/src/main/java/keijumt/devandroid/di/module/AppModule.kt new file mode 100644 index 0000000..9ef89c2 --- /dev/null +++ b/app/src/main/java/keijumt/devandroid/di/module/AppModule.kt @@ -0,0 +1,23 @@ +package keijumt.devandroid.di.module + +import android.app.Application +import android.content.Context +import dagger.Module +import dagger.Provides +import javax.inject.Singleton + +/** + * Module: Application 定義 + */ +@Module(includes = arrayOf( + ViewModelModule::class +)) +class AppModule { + + @Singleton + @Provides + fun provideContext(application: Application): Context { + return application.applicationContext + } + +} \ No newline at end of file diff --git a/app/src/main/java/keijumt/devandroid/di/module/FragmentModule.kt b/app/src/main/java/keijumt/devandroid/di/module/FragmentModule.kt new file mode 100644 index 0000000..7bc38f4 --- /dev/null +++ b/app/src/main/java/keijumt/devandroid/di/module/FragmentModule.kt @@ -0,0 +1,11 @@ +package keijumt.devandroid.di.module + +import dagger.Module + +/** + * Module: Fragment 定義 + */ +@Module +internal abstract class FragmentModule { + +} \ No newline at end of file diff --git a/app/src/main/java/keijumt/devandroid/di/module/ViewModelModule.kt b/app/src/main/java/keijumt/devandroid/di/module/ViewModelModule.kt new file mode 100644 index 0000000..8051124 --- /dev/null +++ b/app/src/main/java/keijumt/devandroid/di/module/ViewModelModule.kt @@ -0,0 +1,26 @@ +package keijumt.devandroid.di.module + +import android.arch.lifecycle.ViewModel +import android.arch.lifecycle.ViewModelProvider +import dagger.Binds +import dagger.MapKey +import dagger.Module +import keijumt.devandroid.viewmodel.ViewModelFactory +import kotlin.reflect.KClass + +@MustBeDocumented +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +@MapKey +internal annotation class ViewModelKey(val value: KClass) + +/** + * Module: ViewModel 定義 + */ +@Module +internal abstract class ViewModelModule { + + @Binds + abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory + +} \ No newline at end of file diff --git a/app/src/main/java/keijumt/devandroid/viewmodel/ViewModelFactory.kt b/app/src/main/java/keijumt/devandroid/viewmodel/ViewModelFactory.kt new file mode 100644 index 0000000..ac22fa9 --- /dev/null +++ b/app/src/main/java/keijumt/devandroid/viewmodel/ViewModelFactory.kt @@ -0,0 +1,32 @@ +package keijumt.devandroid.viewmodel + +import android.arch.lifecycle.ViewModel +import android.arch.lifecycle.ViewModelProvider +import javax.inject.Inject +import javax.inject.Provider + +/** + * Factory: ViewModel + */ +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 model class " + modelClass) + try { + return creator.get() as T + } catch (e: Exception) { + throw RuntimeException(e) + } + } +} \ No newline at end of file