Skip to content

Commit f7af05e

Browse files
authored
add assisted inject (#15)
* add assisted inject * add backing field for arguments * add assisted inject + run spotlessApplly * move initialization to init for consistency with the MainViewModel fix test * change to trailing lambda * revert unused change * remove unused import
1 parent 29583d8 commit f7af05e

File tree

6 files changed

+86
-26
lines changed

6 files changed

+86
-26
lines changed

app/build.gradle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ android {
3535
arguments += ["room.schemaLocation" : "$projectDir/schemas".toString()]
3636
}
3737
}
38+
javaCompileOptions {
39+
annotationProcessorOptions {
40+
arguments["dagger.hilt.disableModulesHaveInstallInCheck"] = "true"
41+
}
42+
}
3843
}
3944
compileOptions {
4045
sourceCompatibility JavaVersion.VERSION_1_8
@@ -103,6 +108,8 @@ dependencies {
103108
implementation "com.google.dagger:hilt-android:$versions.daggerHiltCoreVersion"
104109
implementation "androidx.hilt:hilt-common:$versions.daggerHiltVersion"
105110
implementation "androidx.hilt:hilt-lifecycle-viewmodel:$versions.daggerHiltVersion"
111+
compileOnly "com.squareup.inject:assisted-inject-annotations-dagger2:$versions.assistedInjectVersion"
112+
kapt "com.squareup.inject:assisted-inject-processor-dagger2:$versions.assistedInjectVersion"
106113
kapt "com.google.dagger:hilt-compiler:$versions.daggerHiltCoreVersion"
107114
kapt "androidx.hilt:hilt-compiler:$versions.daggerHiltVersion"
108115
androidTestImplementation "com.google.dagger:hilt-android-testing:$versions.daggerHiltCoreVersion"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Designed and developed by 2020 skydoves (Jaewoong Eum)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.skydoves.pokedex.di
18+
19+
import com.squareup.inject.assisted.dagger2.AssistedModule
20+
import dagger.Module
21+
import dagger.hilt.InstallIn
22+
import dagger.hilt.android.components.ActivityRetainedComponent
23+
24+
// AssistedInject puts all assisted bindings in the same module.
25+
// We need to make a decision about where to install it.
26+
// In this case, as we only need it in activity, we install it there.
27+
// source: https://gist.github.com/manuelvicnt/437668cda3a891d347e134b1de29aee1
28+
@InstallIn(ActivityRetainedComponent::class)
29+
@AssistedModule
30+
@Module(includes = [AssistedInject_AssistedInjectModule::class])
31+
// Needed until AssistedInject is incorporated into Dagger
32+
interface AssistedInjectModule

app/src/main/java/com/skydoves/pokedex/ui/details/DetailActivity.kt

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,34 @@ import com.skydoves.pokedex.model.Pokemon
2929
import com.skydoves.transformationlayout.TransformationCompat
3030
import com.skydoves.transformationlayout.TransformationLayout
3131
import dagger.hilt.android.AndroidEntryPoint
32+
import javax.inject.Inject
3233

3334
@AndroidEntryPoint
3435
class DetailActivity : DataBindingActivity() {
3536

36-
@VisibleForTesting val viewModel: DetailViewModel by viewModels()
37+
@Inject
38+
lateinit var detailViewModelFactory: DetailViewModel.AssistedFactory
39+
40+
@VisibleForTesting
41+
val viewModel: DetailViewModel by viewModels {
42+
DetailViewModel.provideFactory(
43+
detailViewModelFactory,
44+
pokemonItem.name
45+
)
46+
}
47+
3748
private val binding: ActivityDetailBinding by binding(R.layout.activity_detail)
3849

50+
private val pokemonItem: Pokemon
51+
get() = requireNotNull(intent.getParcelableExtra(EXTRA_POKEMON))
52+
3953
override fun onCreate(savedInstanceState: Bundle?) {
4054
onTransformationEndContainerApplyParams()
4155
super.onCreate(savedInstanceState)
42-
val pokemonItem: Pokemon = requireNotNull(intent.getParcelableExtra(EXTRA_POKEMON))
4356
binding.apply {
4457
pokemon = pokemonItem
4558
lifecycleOwner = this@DetailActivity
46-
vm = viewModel.apply { fetchPokemonInfo(pokemonItem.name) }
59+
vm = viewModel
4760
}
4861
}
4962

app/src/main/java/com/skydoves/pokedex/ui/details/DetailViewModel.kt

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,45 +16,56 @@
1616

1717
package com.skydoves.pokedex.ui.details
1818

19-
import androidx.annotation.MainThread
2019
import androidx.databinding.ObservableBoolean
21-
import androidx.hilt.lifecycle.ViewModelInject
2220
import androidx.lifecycle.LiveData
2321
import androidx.lifecycle.MutableLiveData
22+
import androidx.lifecycle.ViewModel
23+
import androidx.lifecycle.ViewModelProvider
2424
import androidx.lifecycle.asLiveData
25-
import androidx.lifecycle.switchMap
2625
import com.skydoves.pokedex.base.LiveCoroutinesViewModel
2726
import com.skydoves.pokedex.model.PokemonInfo
2827
import com.skydoves.pokedex.repository.DetailRepository
28+
import com.squareup.inject.assisted.Assisted
29+
import com.squareup.inject.assisted.AssistedInject
2930
import timber.log.Timber
3031

31-
class DetailViewModel @ViewModelInject constructor(
32-
private val detailRepository: DetailRepository
32+
class DetailViewModel @AssistedInject constructor(
33+
private val detailRepository: DetailRepository,
34+
@Assisted private val pokemonName: String
3335
) : LiveCoroutinesViewModel() {
3436

35-
private var pokemonFetchingLiveData: MutableLiveData<String> = MutableLiveData()
36-
val pokemonInfoLiveData: LiveData<PokemonInfo?>
37-
3837
val isLoading: ObservableBoolean = ObservableBoolean(false)
3938
val toastLiveData: MutableLiveData<String> = MutableLiveData()
39+
val pokemonInfoLiveData: LiveData<PokemonInfo?>
4040

4141
init {
4242
Timber.d("init DetailViewModel")
43-
44-
pokemonInfoLiveData = pokemonFetchingLiveData.switchMap {
45-
isLoading.set(true)
46-
launchOnViewModelScope {
47-
this.detailRepository.fetchPokemonInfo(
48-
name = it,
43+
pokemonInfoLiveData = launchOnViewModelScope(
44+
block = {
45+
isLoading.set(true)
46+
detailRepository.fetchPokemonInfo(
47+
name = pokemonName,
4948
onSuccess = { isLoading.set(false) },
5049
onError = { toastLiveData.postValue(it) }
5150
).asLiveData()
5251
}
53-
}
52+
)
5453
}
5554

56-
@MainThread
57-
fun fetchPokemonInfo(name: String) {
58-
pokemonFetchingLiveData.value = name
55+
@AssistedInject.Factory
56+
interface AssistedFactory {
57+
fun create(pokemonName: String): DetailViewModel
58+
}
59+
60+
companion object {
61+
fun provideFactory(
62+
assistedFactory: AssistedFactory,
63+
pokemonName: String
64+
): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
65+
@Suppress("UNCHECKED_CAST")
66+
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
67+
return assistedFactory.create(pokemonName) as T
68+
}
69+
}
5970
}
6071
}

app/src/test/java/com/skydoves/pokedex/viewmodel/DetailViewModelTest.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import com.skydoves.pokedex.repository.DetailRepository
3333
import com.skydoves.pokedex.ui.details.DetailViewModel
3434
import com.skydoves.pokedex.utils.MockUtil
3535
import kotlinx.coroutines.ExperimentalCoroutinesApi
36-
import kotlinx.coroutines.delay
3736
import kotlinx.coroutines.runBlocking
3837
import org.junit.Before
3938
import org.junit.Rule
@@ -59,7 +58,7 @@ class DetailViewModelTest {
5958
@Before
6059
fun setup() {
6160
detailRepository = DetailRepository(pokdexClient, pokemonInfoDao)
62-
viewModel = DetailViewModel(detailRepository)
61+
viewModel = DetailViewModel(detailRepository, "skydoves")
6362
}
6463

6564
@Test
@@ -76,9 +75,6 @@ class DetailViewModelTest {
7675
).asLiveData()
7776
fetchedData.observeForever(observer)
7877

79-
viewModel.fetchPokemonInfo(name = "skydoves")
80-
delay(500L)
81-
8278
verify(pokemonInfoDao, atLeastOnce()).getPokemonInfo(name_ = "skydoves")
8379
verify(observer).onChanged(mockData)
8480
fetchedData.removeObserver(observer)

dependencies.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ ext.versions = [
4343
// di
4444
daggerHiltCoreVersion: '2.29.1-alpha',
4545
daggerHiltVersion : '1.0.0-alpha02',
46+
assistedInjectVersion: '0.5.2',
4647

4748
// network
4849
retrofitVersion : '2.9.0',

0 commit comments

Comments
 (0)