我试着用Retrofit和Dagger 2调用API,在我的例子中,DataModel和它的模块被注入得很好,但API的模块却没有。我肯定我错过了什么,但不明白是什么。这是我的组件。
@Singleton
@Component(modules = [SMModule::class, SMNetworkModule::class])
interface SMComponent {
fun inject(fragment: SMListFragment)
}
模块:
@Module
class SMModule {
@Provides
fun provideSMModel(): SMListDataModel {
return SMListDataModel()
}
}
@Module
object SMNetworkModule {
@JvmStatic
@Singleton
@Provides
fun provideRetrofit(): Retrofit {
val okHttpBuilder = OkHttpClient.Builder()
if (BuildConfig.DEBUG) {
val httpLoggingInterceptor = HttpLoggingInterceptor()
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
okHttpBuilder.addInterceptor(httpLoggingInterceptor)
}
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpBuilder.build())
.build()
}
@JvmStatic
@Singleton
@Provides
fun provideSMInterface(retrofit: Retrofit): SMInterface =
retrofit.create(SMInterface::class.java)
}
DataModel:
class SMListDataModel @Inject constructor() {
@Inject
lateinit var smApi: SMAPI
override fun loadData(): DataResponse {
return smApi.getData().blockingGet()
}
}
我的API:
@Singleton
class SMAPI @Inject constructor() {
@Inject
lateinit var smInterface: SMInterface
fun getData(): Single<DataResponse> {
return smInterface.getData()
}
}
在这里我注入了我的Fragment并调用DataModel:
@JvmField
@Inject
var dataModel: StocksListDataModel? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DaggerSMComponent.create().inject(this)
}
override fun onResume() {
super.onResume()
val response = dataModel?.loadData()
}
然后我得到一个错误:
UninitializedPropertyAccessException: lateinit property smApi has not been initialized.
内的SMListDataModel。
我看了看 这个问题 在那里,我没有看到API的显式构造函数,它对他们来说是有效的。但对我来说却不行。
我使用这个,它的工作原理很好。(提供Room & Retrofit).我希望它是有用的。
RemoteModule类。
@Module(includes = [AppModule::class])
class RemoteModule {
@Provides
@Singleton
fun provideArticleDatabase(application: App): RoomDataBase? {
return Room.databaseBuilder(
application.applicationContext,
RoomDataBase::class.java,
"fandogh"
)
.build()
}
@Provides
fun provideArticleDao(@Nullable articleDatabase: RoomDataBase): ILocalDataSource? {
return articleDatabase.roomDao()
}
@Provides
@ApplicationScope
fun getApiInterface(retroFit: Retrofit): ApiService {
return retroFit.create(ApiService::class.java)
}
@Provides
@ApplicationScope
fun getRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
// .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build()
}
@Provides
@ApplicationScope
fun getOkHttpCleint(httpLoggingInterceptor: HttpLoggingInterceptor, myAuthHeaderInterceptor: MyAuthHeaderInterceptor): OkHttpClient {
return OkHttpClient.Builder()
.readTimeout(30, TimeUnit.SECONDS)
.connectTimeout(30, TimeUnit.SECONDS)
.callTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
// .addInterceptor {
// var request = it.request().newBuilder().addHeader("authorization", Constants.AUTHORIZATION_HEADER).build()
// return@addInterceptor it.proceed(request)
// }
.addInterceptor(myAuthHeaderInterceptor)
.addInterceptor(httpLoggingInterceptor)
.build()
}
@Provides
@ApplicationScope
fun getHttpLoggingInterceptor(): HttpLoggingInterceptor {
val httpLoggingInterceptor = HttpLoggingInterceptor()
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
return httpLoggingInterceptor
}
@Singleton
@Provides
fun getAuthHeaderInterceptor(sharedPrefrences: SharedPreferences): MyAuthHeaderInterceptor {
return MyAuthHeaderInterceptor(sharedPrefrences)
}
}
ViewModelModule。
@Module
abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(factory: DaggerViewModelFactory): ViewModelProvider.Factory // this needs to be only one for whole app (therefore marked as `@Singleton`)
@Binds
@IntoMap
@ViewModelKey(LoginViewModel::class)
abstract fun loginViewModel(viewModel: LoginViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(ActMainViewModel::class)
abstract fun mainActivityViewModel(viewModel: ActMainViewModel): ViewModel
}
FragmentBuilder。
@Module
abstract class FragmentBuilder {
@FragmentScope
@ContributesAndroidInjector
abstract fun homeFragment(): HomeFragment?
}
ActivityBuilder:活动生成器。
@Module
abstract class ActivityBuilder {
@ActivityScope
@ContributesAndroidInjector
abstract fun loginActivity(): ActivityLogin?
@ActivityScope
@ContributesAndroidInjector
abstract fun mainActivity(): MainActivity?
}
AppModule:AppModule:ActivityBuilder:AppModule。
@Module
abstract class AppModule {
@Binds
@Singleton
abstract fun application(app: App?): Application?
}
ActivityScope : ActivityScope:ActivityBuilder:AppModule:AppModule。
@Scope
@Retention(value = AnnotationRetention.RUNTIME)
annotation class ActivityScope
FragmentScope : FragmentScope :
@Scope
@Retention(value = AnnotationRetention.RUNTIME)
annotation class FragmentScope {
}
AppComponent:AppComponent。
@Singleton
@ApplicationScope
@Component(
modules = [AppModule::class, AndroidSupportInjectionModule::class, RemoteModule::class, ActivityBuilder::class,
FragmentBuilder::class, ViewModelModule::class]
)
interface AppComponent : AndroidInjector<App> {
fun inject(membersFragment: MembersFragment)
override fun inject(myApplication: App)
fun inject(instance: DaggerApplication)
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: App): Builder
fun build(): AppComponent
}
}
应用程序。
class App : DaggerApplication() {
var appComponent: AppComponent? = null
override fun applicationInjector(): AppComponent {
appComponent = DaggerAppComponent.builder().application(this).build()
appComponent!!.inject(this)
return appComponent!!
}
}
并在ViewModel中使用。
class LoanViewModel @Inject constructor() : ViewModel() {
@Inject
lateinit var apiService: ApiService
}