forked from element-hq/element-x-android
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
ganfra
committed
Dec 9, 2022
1 parent
88a7be2
commit 0b00bcf
Showing
22 changed files
with
290 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
plugins { | ||
alias(libs.plugins.kotlin.jvm) | ||
} | ||
|
||
dependencies { | ||
api(libs.inject) | ||
} |
17 changes: 17 additions & 0 deletions
17
anvilannotations/src/main/java/io/element/android/x/anvilannotations/ContributesViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package io.element.android.x.anvilannotations | ||
|
||
import kotlin.reflect.KClass | ||
|
||
/** | ||
* Adds view model to the specified component graph. | ||
* Equivalent to the following declaration in a dagger module: | ||
* | ||
* @Binds | ||
* @IntoMap | ||
* @ViewModelKey(YourViewModel::class) | ||
* public abstract fun bindYourViewModelFactory(factory: YourViewModel.Factory): AssistedViewModelFactory<*, *> | ||
*/ | ||
@Target(AnnotationTarget.CLASS) | ||
annotation class ContributesViewModel( | ||
val scope: KClass<*>, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
plugins { | ||
alias(libs.plugins.kotlin.jvm) | ||
alias(libs.plugins.kapt) | ||
} | ||
|
||
/* | ||
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { | ||
kotlinOptions { | ||
freeCompilerArgs += listOf( | ||
"-opt-in=com.squareup.anvil.annotations.ExperimentalAnvilApi") | ||
} | ||
} | ||
*/ | ||
|
||
dependencies { | ||
implementation(project(":anvilannotations")) | ||
api(libs.anvil.compiler.api) | ||
implementation(libs.anvil.compiler.utils) | ||
implementation("com.squareup:kotlinpoet:1.10.2") | ||
implementation(libs.dagger) | ||
compileOnly("com.google.auto.service:auto-service-annotations:1.0.1") | ||
kapt("com.google.auto.service:auto-service:1.0.1") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
libraries/core/src/main/java/io/element/android/x/core/di/AssistedViewModelFactory.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright (c) 2021 New Vector Ltd | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package io.element.android.x.core.di | ||
|
||
import com.airbnb.mvrx.MavericksState | ||
import com.airbnb.mvrx.MavericksViewModel | ||
|
||
interface AssistedViewModelFactory<VM : MavericksViewModel<S>, S : MavericksState> { | ||
fun create(initialState: S): VM | ||
} |
53 changes: 53 additions & 0 deletions
53
libraries/core/src/main/java/io/element/android/x/core/di/Bindings.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package io.element.android.x.core.di | ||
|
||
import android.content.Context | ||
import android.content.ContextWrapper | ||
import androidx.fragment.app.Fragment | ||
|
||
/** | ||
* Use this to get the Dagger "Bindings" for your module. Bindings are used if you need to directly interact with a dagger component such as: | ||
* * an inject function: `inject(MyFragment frag)` | ||
* * an explicit getter: `fun myClass(): MyClass` | ||
* | ||
* Anvil will make your Dagger component implement these bindings so that you can call any of these functions on an instance of your component. | ||
* | ||
* [bindings] will walk up the Fragment/Activity hierarchy and check for [DaggerComponentOwner] to see if any of its components implement the | ||
* specified bindings. Most of the time this will "just work" and you don't have to think about it. | ||
* | ||
* For example, if your class has @Inject properties: | ||
* 1) Create an bindings interface such as `YourModuleBindings` | ||
* 1) Add an inject function like `fun inject(yourClass: YourClass)` | ||
* 2) Contribute your interface to the correct component via `@ContributesTo(AppScope::class)`. | ||
* 3) Call bindings<YourModuleBindings>().inject(this). | ||
*/ | ||
inline fun <reified T : Any> Context.bindings() = bindings(T::class.java) | ||
|
||
/** | ||
* @see bindings | ||
*/ | ||
inline fun <reified T : Any> Fragment.bindings() = bindings(T::class.java) | ||
|
||
/** Use no-arg extension function instead: [Context.bindings] */ | ||
fun <T : Any> Context.bindings(klass: Class<T>): T { | ||
// search dagger components in the context hierarchy | ||
return generateSequence(this) { (it as? ContextWrapper)?.baseContext } | ||
.plus(applicationContext) | ||
.filterIsInstance<DaggerComponentOwner>() | ||
.map { it.daggerComponent } | ||
.flatMap { if (it is Collection<*>) it else listOf(it) } | ||
.filterIsInstance(klass) | ||
.firstOrNull() | ||
?: error("Unable to find bindings for ${klass.name}") | ||
} | ||
|
||
/** Use no-arg extension function instead: [Fragment.bindings] */ | ||
fun <T : Any> Fragment.bindings(klass: Class<T>): T { | ||
// search dagger components in fragment hierarchy, then fallback to activity and application | ||
return generateSequence(this, Fragment::getParentFragment) | ||
.filterIsInstance<DaggerComponentOwner>() | ||
.map { it.daggerComponent } | ||
.flatMap { if (it is Collection<*>) it else listOf(it) } | ||
.filterIsInstance(klass) | ||
.firstOrNull() | ||
?: requireActivity().bindings(klass) | ||
} |
10 changes: 10 additions & 0 deletions
10
libraries/core/src/main/java/io/element/android/x/core/di/DaggerComponentOwner.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package io.element.android.x.core.di | ||
|
||
/** | ||
* A [DaggerComponentOwner] is anything that "owns" a Dagger Component. | ||
* | ||
*/ | ||
interface DaggerComponentOwner { | ||
/** This is either a component, or a list of components. */ | ||
val daggerComponent: Any | ||
} |
68 changes: 68 additions & 0 deletions
68
libraries/core/src/main/java/io/element/android/x/core/di/DaggerMavericksViewModelFactory.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package io.element.android.x.core.di | ||
|
||
import com.airbnb.mvrx.FragmentViewModelContext | ||
import com.airbnb.mvrx.MavericksState | ||
import com.airbnb.mvrx.MavericksViewModel | ||
import com.airbnb.mvrx.MavericksViewModelFactory | ||
import com.airbnb.mvrx.ViewModelContext | ||
|
||
/** | ||
* To connect Mavericks ViewModel creation with Anvil's dependency injection, add the following to your MavericksViewModel. | ||
* | ||
* Example: | ||
* | ||
* @ContributesViewModel(YourScope::class) | ||
* class MyViewModel @AssistedInject constructor( | ||
* @Assisted initialState: MyState, | ||
* …, | ||
* ): MavericksViewModel<MyState>(...) { | ||
* … | ||
* | ||
* companion object : MavericksViewModelFactory<MyViewModel, MyState> by daggerMavericksViewModelFactory() | ||
* } | ||
*/ | ||
|
||
inline fun <reified VM : MavericksViewModel<S>, S : MavericksState> daggerMavericksViewModelFactory() = DaggerMavericksViewModelFactory<VM, S>(VM::class.java) | ||
|
||
/** | ||
* A [MavericksViewModelFactory] makes it easy to create instances of a ViewModel | ||
* using its AssistedInject Factory. This class should be implemented by the companion object | ||
* of every ViewModel which uses AssistedInject via [daggerMavericksViewModelFactory]. | ||
* | ||
* @param viewModelClass The [Class] of the ViewModel being requested for creation | ||
* | ||
* This class accesses the map of ViewModel class to [AssistedViewModelFactory]s from the nearest [DaggerComponentOwner] and | ||
* uses it to retrieve the requested ViewModel's factory class. It then creates an instance of this ViewModel | ||
* using the retrieved factory and returns it. | ||
* @see daggerMavericksViewModelFactory | ||
*/ | ||
class DaggerMavericksViewModelFactory<VM : MavericksViewModel<S>, S : MavericksState>( | ||
private val viewModelClass: Class<VM> | ||
) : MavericksViewModelFactory<VM, S> { | ||
|
||
override fun create(viewModelContext: ViewModelContext, state: S): VM { | ||
val bindings: DaggerMavericksBindings = when (viewModelContext) { | ||
is FragmentViewModelContext -> viewModelContext.fragment.bindings() | ||
else -> viewModelContext.activity.bindings() | ||
} | ||
val viewModelFactoryMap = bindings.viewModelFactories() | ||
val viewModelFactory = viewModelFactoryMap[viewModelClass] ?: error("Cannot find ViewModelFactory for ${viewModelClass.name}.") | ||
|
||
@Suppress("UNCHECKED_CAST") | ||
val castedViewModelFactory = viewModelFactory as? AssistedViewModelFactory<VM, S> | ||
val viewModel = castedViewModelFactory?.create(state) | ||
return viewModel as VM | ||
} | ||
} | ||
|
||
/** | ||
* These Anvil/Dagger bindings are used by [DaggerMavericksViewModelFactory]. The factory will find the nearest [DaggerComponentOwner] | ||
* that implements these bindings. It will then attempt to retrieve the [AssistedViewModelFactory] for the given ViewModel class. | ||
* | ||
* In this example, this bindings class is implemented by [com.airbnb.mvrx.sample.anvil.feature.ExampleFeatureComponent] because | ||
* it provides the [com.airbnb.mvrx.sample.anvil.feature.ExampleFeatureViewModel]. Any component that will generate ViewModels should | ||
* either implement this directly or have this added via `@ContributesTo(YourScope::class)`. | ||
*/ | ||
interface DaggerMavericksBindings { | ||
fun viewModelFactories(): Map<Class<out MavericksViewModel<*>>, AssistedViewModelFactory<*, *>> | ||
} |
26 changes: 26 additions & 0 deletions
26
libraries/core/src/main/java/io/element/android/x/core/di/ViewModelKey.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* Copyright 2019 New Vector Ltd | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package io.element.android.x.core.di | ||
|
||
import com.airbnb.mvrx.MavericksViewModel | ||
import dagger.MapKey | ||
import kotlin.reflect.KClass | ||
|
||
@Retention(AnnotationRetention.RUNTIME) | ||
@Target(AnnotationTarget.FUNCTION) | ||
@MapKey | ||
annotation class ViewModelKey(val value: KClass<out MavericksViewModel<*>>) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
plugins { | ||
alias(libs.plugins.kotlin.jvm) | ||
} | ||
|
||
dependencies { | ||
api(libs.inject) | ||
} |
3 changes: 3 additions & 0 deletions
3
libraries/daggerscopes/src/main/java/io/element/android/x/di/AppScope.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package io.element.android.x.di | ||
|
||
abstract class AppScope private constructor() |
3 changes: 3 additions & 0 deletions
3
libraries/daggerscopes/src/main/java/io/element/android/x/di/SessionScope.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package io.element.android.x.di | ||
|
||
abstract class SessionScope private constructor() |
8 changes: 8 additions & 0 deletions
8
libraries/daggerscopes/src/main/java/io/element/android/x/di/SingleIn.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package io.element.android.x.di | ||
|
||
import javax.inject.Scope | ||
import kotlin.reflect.KClass | ||
|
||
@Scope | ||
@Retention(AnnotationRetention.RUNTIME) | ||
annotation class SingleIn(val clazz: KClass<*>) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.