I wrote network module in project. I checked all similiar codes and qustions there are some people have same problem. But they all didn't solve this problem for me. I don't know what is problem here.
This is the error:
error: #Provides methods can only be present within a #Module or #ProducerModule
public static final com.technoface.iga.api.BoardingPassService postBoardingPassesRead(#org.jetbrains.annotations.NotNull()
NetworkModule.kt
#Module
#InstallIn(SingletonComponent::class)
object NetworkModule {
#Singleton
#Provides
fun provideBaseUrl() = BuildConfig.BASE_URL
#Provides
#Singleton
fun provideLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
}
#ServiceInterceptorOkHttpClient
#Singleton
#Provides
fun providesServiceInterceptor(clientPreferences: ClientPreferences): ServiceInterceptor =
ServiceInterceptor(clientPreferences)
#Provides
#Singleton
fun provideOkHttpClient(
logging: HttpLoggingInterceptor,
#ServiceInterceptorOkHttpClient
serviceInterceptor: ServiceInterceptor
): OkHttpClient {
return OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.addInterceptor(logging)
.addInterceptor(serviceInterceptor)
.build()
}
#Provides
#Singleton
fun provideNetworkResultCallAdapterFactory(): CallAdapter.Factory {
return NetworkResultCallAdapterFactory.create()
}
#Provides
#Singleton
fun provideRetrofit(client: OkHttpClient, callAdapterFactory: CallAdapter.Factory): Retrofit {
return Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(callAdapterFactory)
.client(client)
.build()
}
#Provides
#Singleton
fun postBoardingPassesRead(serviceBuilder: ServiceBuilder): BoardingPassService = serviceBuilder.buildService(BoardingPassService::class.java)
#Qualifier
#Retention(AnnotationRetention.BINARY)
annotation class BaseUrl
#Qualifier
#Retention(AnnotationRetention.BINARY)
annotation class ServiceInterceptorOkHttpClient
BoardingPassServiceRepo.kt
class BoardingPassServiceRepo #Inject constructor(
private val boardingPassService: BoardingPassService
) {
suspend fun postBoardingPassesRead(boardingPassInfoRequest: BoardingPassInfoRequest) = boardingPassService.postBoardingPassesRead(
encryptData(boardingPassInfoRequest)
)
}
AppModule.kt
#Module
#InstallIn(SingletonComponent::class)
object AppModule {
#Singleton
#Provides
fun provideClientPreferences(
#ApplicationContext context: Context
) = ClientPreferences(context)
}
class BoardingPassServiceRepo #Inject constructor(
private val boardingPassService: BoardingPassService
) {
suspend fun postBoardingPassesRead(boardingPassInfoRequest: BoardingPassInfoRequest) = boardingPassService.postBoardingPassesRead(
encryptData(boardingPassInfoRequest)
)
}
Update Gradle version.
Changed gradle version.
Clean, Rebuild, Invalidate cache
Deactivated Antivirus.
Related
I am new with dagger using. So, I can't solve whats the problem with this. I just want to ask here to solve it.
This is the error:
C:\Users\msi\Documents\MyAndroidProjects\MovieProjects\app\build\generated\hilt\component_sources\debug\com\example\movieapp\App_HiltComponents.java:128:
error: [Dagger/MissingBinding]
com.example.movieapp.api.MovieAppService cannot be provided without an
#Provides-annotated method. public abstract static class SingletonC
implements App_GeneratedInjector,
^
com.example.movieapp.api.MovieAppService is injected at
com.example.movieapp.repository.MovieRepository(movieAppService)
com.example.movieapp.repository.MovieRepository is injected at
com.example.movieapp.viewmodel.MainViewModel(repository, �)
com.example.movieapp.viewmodel.MainViewModel is injected at
com.example.movieapp.viewmodel.MainViewModel_HiltModules.BindsModule.binds(arg0)
#dagger.hilt.android.internal.lifecycle.HiltViewModelMap java.util.Map<java.lang.String,javax.inject.Provider<androidx.lifecycle.ViewModel>>
is requested at
dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.ViewModelFactoriesEntryPoint.getHiltViewModelMap()
[com.example.movieapp.App_HiltComponents.SingletonC ?
com.example.movieapp.App_HiltComponents.ActivityRetainedC ?
com.example.movieapp.App_HiltComponents.ViewModelC]
MainViewModel.kt
#HiltViewModel
class MainViewModel#Inject constructor(
private val repository: MovieRepository,
#ApplicationContext private val context: Context
) : ViewModel() {
val movieList = MutableLiveData<Resource<Movie>>()
fun getAllMovies(movieName: String) {
movieList.postValue(Resource.Loading())
viewModelScope.launch {
try {
if (hasInternetConnection(context)) {
val response = repository.getMovies(movieName, "ffe9063f")
movieList.postValue(Resource.Success(response.body()!!))
} else
movieList.postValue(Resource.Error("Internet yok"))
} catch (ex: Exception) {
when (ex) {
is IOException -> movieList.postValue(Resource.Error("Network Failure " + ex.localizedMessage))
else -> movieList.postValue(Resource.Error("Conversion Error"))
}
}
}
}
}
MovieRepository.kt
#Singleton
class MovieRepository #Inject constructor(private val movieAppService: MovieAppService) {
suspend fun getMovies(title: String, aKey: String): Response<Movie> = withContext(
Dispatchers.IO
) {
val movies = movieAppService.getMovies(title = title, aKey = aKey)
movies
}
}
ApiModule.kt
class ApiModule {
#Module
#InstallIn(SingletonComponent::class)
object ApiModule {
#Provides
#Singleton
fun provideLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
}
#Provides
#Singleton
fun provideOkHttpClient(logging: HttpLoggingInterceptor): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(logging)
.connectTimeout(15, TimeUnit.SECONDS) // connect timeout
.readTimeout(15, TimeUnit.SECONDS)
.build()
}
#Provides
#Singleton
fun provideRetrofit(client: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
}
#Provides
#Singleton
fun provideMovieAppService(retrofit: Retrofit): MovieAppService {
return retrofit.create(MovieAppService::class.java)
}
}
}
MovieAppService.kt
interface MovieAppService {
companion object {
const val ENDPOINT = "http://www.omdbapi.com/"
}
#GET(".")
suspend fun getMovies(#Query("t") title: String,#Query("apikey") aKey: String): Response<Movie>
}
Do not wrap your singleton object module with a same named class. Change your module file like this or change your class name
#Module
#InstallIn(SingletonComponent::class)
object ApiModule {
#Provides
#Singleton
fun provideLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
}
#Provides
#Singleton
fun provideOkHttpClient(logging: HttpLoggingInterceptor): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(logging)
.connectTimeout(15, TimeUnit.SECONDS) // connect timeout
.readTimeout(15, TimeUnit.SECONDS)
.build()
}
#Provides
#Singleton
fun provideRetrofit(client: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
}
#Provides
#Singleton
fun provideMovieAppService(retrofit: Retrofit): MovieAppService {
return retrofit.create(MovieAppService::class.java)
}
}
I have a problem with injection dagger into view model.The problem is that losing form inputs when rotating the screen.Is the problem in my injection or initialize my view model? Here is my viewmodel;
#HiltViewModel
class ProfilIslemViewModel #Inject constructor(application: Application,
private val kullaniciService: KullaniciService,
private val kullaniciDao:KullaniciDao
): AndroidViewModel(application), CoroutineScope {...}
And here is my fragment that use this view model;
#AndroidEntryPoint
class ProfilIslemFragment:Fragment(), ProfilIslemFragmentClickListener {
private val viewModel: ProfilIslemViewModel by viewModels();
...
}
Here is the module that injected class;
#Module
#InstallIn(SingletonComponent::class)
object KutuphanemAppModule {
#Singleton
#Provides
fun provideKutuphanemDatabase
(#ApplicationContext context:Context) = Room.databaseBuilder(
context,
KutuphanemDatabase::class.java,
KUTUPHANEM_DB_NAME
).build();
#Singleton
#Provides
fun provideRetrofit(client: OkHttpClient):Retrofit =
Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
#Singleton
#Provides
fun provideHttpClient(customSharedPreferences: CustomSharedPreferences):OkHttpClient{
return OkHttpClient.Builder().addInterceptor(object:Interceptor{
override fun intercept(chain: Interceptor.Chain): Response {
val request:Request = chain.request().newBuilder().addHeader("Authorization",
"Bearer "+customSharedPreferences.getStringFromSharedPreferences(APP_TOKEN_KEY).trim()).build();
return chain.proceed(request);
}
}).build();
}
#Singleton
#Provides
fun provideParametreDao(database: KutuphanemDatabase) = database.getParametreDao();
#Singleton
#Provides
fun provideParametreApi(retrofit: Retrofit):IParametreService = retrofit.create(IParametreService::class.java);
#Singleton
#Provides
fun provideKullaniciApi(retrofit: Retrofit):KullaniciService = retrofit.create(KullaniciService::class.java);
#Singleton
#Provides
fun provideKitapApi(retrofit: Retrofit):IKitapService = retrofit.create(IKitapService::class.java);
#Singleton
#Provides
fun provideKullaniciDao(database: KutuphanemDatabase) = database.getKullaniciDao();
}
When I rotate the screen the inputs are losing. How to solve this problem?
I found the error. It is not relevant my view model or injections. It caused by two way databinding. But even so I put this line into the contructor of viewmodel;
private val savedStateHandle: SavedStateHandle
I am controlling the state with this param.So my inputs are not losing.
Im working on trying to provide my API service into a FragmentModule but its not working the way I have setup my Dependency injection, Im receiving a MissingBiding Error even though I have include the corresponding modules into the FragmentModule.
This is my setup:
AppModule
#Module
#InstallIn(value = [SingletonComponent::class])
object AppModule {
#Provides
fun provideApplication(application: MyApplication): Context = application
}
NetworkModule
#Module(includes = [AppModule::class])
#InstallIn(value = [SingletonComponent::class])
object NetworkModule {
private const val BASE_URL = "https://url.co/"
#Provides
fun provideAPI(retrofit: Retrofit): APIService = retrofit.create(APIService::class.java)
#Provides
fun provideCache(cacheFile: File): Cache = Cache(cacheFile, 10 * 1024 * 1024)
#Provides
fun provideFile(#ApplicationContext context: Context): File = File(context.cacheDir, "okhttp_cache")
#Provides
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit =
Retrofit.Builder().client(okHttpClient)
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
#Provides
fun provideOkHttpClient(interceptor: HttpLoggingInterceptor, cache: Cache, context: Context): OkHttpClient {
return OkHttpClient.Builder()
.cache(cache)
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build()
}
}
MyFragmentModule
#Module(includes = [AppModule::class, NetworkModule::class])
#InstallIn(SingletonComponent::class)
object MyFragmentModule {
#Provides
fun provideMyRepositoryImpl(#IoDispatcher
dispatcher: CoroutineDispatcher,
functions: Functions,
apiService: APIService): MyRepository = MyRepositoryImpl(dispatcher, functions, apiService)
#Provides
fun provideMyUseCase(myRepository: MyRepository): MyUseCase = MyUseCase(myRepository)
}
[Dagger/MissingBinding]
C:\MyApplication_HiltComponents.java:168: error: [Dagger/MissingBinding] MyApplication cannot be provided without an #Inject constructor or an #Provides-annotated method. This type supports members injection but cannot be implicitly provided.
public abstract static class SingletonC implements MyApplication_GeneratedInjector,
^
A binding with matching key exists in component: MyApplication_HiltComponents.SingletonC
MyApplication is injected at
di.AppModule.provideApplication(application)
android.content.Context is injected at
di.NetworkModule.provideOkHttpClient(�, context)
okhttp3.OkHttpClient is injected at
di.NetworkModule.provideRetrofit(okHttpClient)
retrofit2.Retrofit is injected at
di.NetworkModule.provideAPI(retrofit)
data.service.APIService is injected at
ui.main_activity.ranking.di.MyFragmentModule.provideMyRepositoryImpl(�, apiService)
ui.main_activity.ranking.data.MyRepository.MyRepository is injected at
ui.main_activity.ranking.di.MyFragmentModule.provideMyUseCase(rankingMyRepository)
javax.inject.Provider<ui.main_activity.ranking.domain.MyUseCase> is injected at
ui.main_activity.ranking.data.view_model.RankingViewModel_AssistedFactory(MyUseCase)
ui.main_activity.ranking.data.view_model.RankingViewModel_AssistedFactory is injected at
ui.main_activity.ranking.data.view_model.RankingViewModel_HiltModule.bind(factory)
java.util.Map<java.lang.String,javax.inject.Provider<androidx.hilt.lifecycle.ViewModelAssistedFactory<? extends androidx.lifecycle.ViewModel>>> is injected at
androidx.hilt.lifecycle.ViewModelFactoryModules.ActivityModule.provideFactory(�, viewModelFactories)
#dagger.hilt.android.internal.lifecycle.DefaultActivityViewModelFactory java.util.Set<androidx.lifecycle.ViewModelProvider.Factory> is injected at
dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.InternalFactoryFactory(�, defaultActivityFactorySet, �)
dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.InternalFactoryFactory is requested at
dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.ActivityEntryPoint.getHiltInternalFactoryFactory() [MyApplication_HiltComponents.SingletonC ? MyApplication_HiltComponents.ActivityRetainedC ? MyApplication_HiltComponents.ActivityC]
The following other entry points also depend on it:
dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.FragmentEntryPoint.getHiltInternalFactoryFactory() [MyApplication_HiltComponents.SingletonC ? MyApplication_HiltComponents.ActivityRetainedC ? MyApplication_HiltComponents.ActivityC ? MyApplication_HiltComponents.FragmentC]
If you have any feedback, i'd very greatefull, thank you
For anyone who is facing a similar issue, be careful by how you defined your modules, in my case i had a #Provides with context instead of MyApp, I also included the #ApplicationContext in the network module, and that solved the issue
#Provides
fun provideApplication(application: MyApplication): MyApplication = application
Added the context annotation:
#Provides
fun provideFile(#ApplicationContext context: Context): File = File(context.cacheDir, "okhttp_cache")
#Provides
fun provideOkHttpClient(interceptor: HttpLoggingInterceptor, cache: Cache, #ApplicationContext context: Context): OkHttpClient {
return OkHttpClient.Builder()
.cache(cache)
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build()
}
I am converting one my project into kotlin source code.
While building the dagger I am encountered with this problem
cannot be provided without an #Inject constructor or an #Provides-annotated method.
I have 2 modules as below
#Module
class AppClient {
#Provides
#Singleton
fun provideHttpCache(application: Application): Cache {
val cacheSize = 10 * 1024 * 1024
return Cache(application.cacheDir, cacheSize.toLong())
}
#Provides
#Singleton
fun provideGson(): Gson {
val gsonBuilder = GsonBuilder()
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
// gsonBuilder.excludeFieldsWithoutExposeAnnotation();
return gsonBuilder.create()
}
#Provides
#Singleton
fun provideOkhttpClient(cache: Cache): OkHttpClient {
val interceptor = HttpLoggingInterceptor()
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
val client = OkHttpClient.Builder()
client.cache(cache)
client.addInterceptor(interceptor)
return client.build()
}
#Provides
#Singleton
fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(NetworkConstant.BASE_URL)
.client(okHttpClient)
.build()
}
#Provides
#Singleton
fun provideApiCall(retrofit: Retrofit): NetworkCall {
return retrofit.create(NetworkCall::class.java)
}
#Provides
#Singleton
fun provideSharedPreference(application: Application): SharedPreferences {
return application.applicationContext.getSharedPreferences(
application.getString(R.string.shared_pref_name),
MODE_PRIVATE
)
}
#Provides
#Singleton
fun provideSharedPreferenceEditor(sharedPreferences: SharedPreferences): SharedPreferences.Editor {
return sharedPreferences.edit()
}
#Provides
#Singleton
fun provideAppPresenter(
sharedPreferences: SharedPreferences, editor: SharedPreferences.Editor,
apiCall: NetworkCall): AppPresenter {
return AppPresenter(sharedPreferences, editor, apiCall)
}
}
And the second module
#Module
class AppModule(val application: MyApplication) {
#Provides
#Singleton
internal fun provideApplication(): MyApplication {
return application
}
}
Application class
class MyApplication : Application() {
lateinit var mApiComponent: AppComponent
override fun onCreate() {
super.onCreate()
mApiComponent = DaggerAppComponent.builder()
.appModule(AppModule(this))
.appClient(AppClient())
.build()
}
fun getAppComponent(): AppComponent {
return mApiComponent
}
}
And the component interface
#Singleton
#Component(modules = [AppModule::class, AppClient::class])
interface AppComponent {
fun inject(activity: LoginActivity)
}
Can someone help out as to what's wrong here?
It seems I was passing the wrong application class. So silly of me
I am using from bellow sample:
New Android Injector with Dagger 2
How can I define my SQLite Connection and retrofit and etc... in this class AppModule
Here is an example how you can do it. Hope this would help.
#Module
class AppModule(val app: Context) {
#Provides
#Singleton
fun provideContext(): Context = app
#Provides
#Singleton
fun provideDatabase(context: Context): Database = Room.databaseBuilder(context, Database::class.java, "my_db").build()
#Provides
#Singleton
fun provideUserDao(database: Database): UserDao = database.userDao()
#Provides
#Singleton
fun providePostDao(database: Database): PostDao = database.postDao()
#Provides
#Singleton
fun provideCommentsDao(database: Database): CommentDao = database.commentDao()
#Provides
#Singleton
fun provideHttpLogging(): HttpLoggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
#Provides
#Singleton
fun provideOkHttpClient(loggingInterceptor: HttpLoggingInterceptor): OkHttpClient =
OkHttpClient.Builder().addInterceptor(loggingInterceptor).build()
#Provides
#Singleton
fun provideJackson(): JacksonConverterFactory = JacksonConverterFactory.create()
#Provides
#Singleton
fun provideRetrofit(okHttpClient: OkHttpClient, jackson: JacksonConverterFactory): Retrofit = Retrofit.Builder()
.client(okHttpClient)
.baseUrl(baseUrl)
.addConverterFactory(jackson)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
#Provides
#Singleton
fun provideApiInterface(retrofit: Retrofit): ApiInterface = retrofit.create(
ApiInterface::class.java
)
}