收到错误试图访问该方法为“不能没有一个@提供提供注解法”

问题描述 投票:0回答:1

我宣布有哪几种方法之一ApplicationComponent。当我尝试在任何片段或活动的应用程序组件的访问方法,我可以通过建立应用级的compoent,但是当我把这个ApplicationComponent到一些其他的组件作为依赖,而现在当我尝试访问该方法时说“无@提供注解方法不能被提供。”。

以前,当我使用像这样在Java中,我能够访问任何其他组件类ApplicationComponent类的方法,但在科特林,我无法访问。请帮我解决这个问题。!

这里,是我已经尝试了代码。

LmsApplicationComponent.kt

package com.satincreditcare.satin.android.dagger.component

import android.arch.lifecycle.ViewModelProvider
import com.satincreditcare.satin.android.dagger.module.RepositoryModule
import com.satincreditcare.satin.android.dagger.module.RetrofitServiceModule
import com.satincreditcare.satin.android.dagger.qualifier.LMSApplicationQualifier
import com.satincreditcare.satin.android.dagger.qualifier.LMSAuthQualifier
import com.satincreditcare.satin.android.dagger.scope.LmsAndroidApplicationScope
import com.satincreditcare.satin.android.network.rest_controller.RestInterface
import dagger.Component

/**
 * Created by Abhishek Jha on 1/28/2019.
 */
@LmsAndroidApplicationScope
@Component(modules = [(RetrofitServiceModule::class), (RepositoryModule::class)])
open interface LmsApplicationComponent {

    @LMSApplicationQualifier
    fun getRestInterface():RestInterface

    @LMSApplicationQualifier
    fun provideViewModelFactory(): ViewModelProvider.Factory

    @LMSAuthQualifier
    fun getAuthRestInterface():RestInterface

    @LMSAuthQualifier
    fun provideAuthViewModelFactory(): ViewModelProvider.Factory

}

在这里,我已经包含了两个模块,即RetrofitServiceModule和RepositoryModule。

RetrofitServiceModule.kt

package com.satincreditcare.satin.android.dagger.module

import android.content.Context
import com.fatboyindustrial.gsonjodatime.DateTimeConverter
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.satincreditcare.satin.android.constants.REST_API
import com.satincreditcare.satin.android.network.rest_controller.RestInterface
import com.satincreditcare.satin.android.dagger.qualifier.LMSApplicationQualifier
import com.satincreditcare.satin.android.dagger.qualifier.LMSAuthQualifier
import com.satincreditcare.satin.android.dagger.scope.LmsAndroidApplicationScope
import dagger.Module
import dagger.Provides
import okhttp3.OkHttpClient
import org.joda.time.DateTime
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory

/**
 * Created by Abhishek Jha on 1/29/2019.
 */
@Module(includes = [(NetworkModule::class)])
open class RetrofitServiceModule {

    @Provides
    @LmsAndroidApplicationScope
    @LMSApplicationQualifier
    fun restInterface(@LMSApplicationQualifier retrofit: Retrofit): RestInterface{
        return retrofit.create(RestInterface::class.java)
    }

    @Provides
    @LmsAndroidApplicationScope
    @LMSApplicationQualifier
    fun retrofit(gson: Gson, @LMSApplicationQualifier okHttpClient: OkHttpClient,
                          @LMSApplicationQualifier baseUrl: String): Retrofit{
        return Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(okHttpClient)
                .baseUrl(baseUrl)
                .build()
    }

    @Provides
    @LmsAndroidApplicationScope
    @LMSApplicationQualifier
    fun baseUrl(context: Context): String{
        return REST_API.getInstance(context).API
    }

    @Provides
    @LmsAndroidApplicationScope
    fun gson(): Gson{
        val gsonBuilder: GsonBuilder = GsonBuilder()
        gsonBuilder.registerTypeAdapter(DateTime::class.java, DateTimeConverter())
        return gsonBuilder.create()
    }


    @Provides
    @LmsAndroidApplicationScope
    @LMSAuthQualifier
    fun restInterfaceAuth(@LMSAuthQualifier retrofit: Retrofit): RestInterface{
        return retrofit.create(RestInterface::class.java)
    }

    @Provides
    @LmsAndroidApplicationScope
    @LMSAuthQualifier
    fun retrofitAuth(gson: Gson, @LMSAuthQualifier okHttpClient: OkHttpClient,
                              @LMSAuthQualifier baseUrl: String): Retrofit{
        return Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(okHttpClient)
                .baseUrl(baseUrl)
                .build()
    }

    @Provides
    @LmsAndroidApplicationScope
    @LMSAuthQualifier
    fun baseUrlAuth(context: Context): String{
        return REST_API.getInstance(context).OAUTH_URL
    }
}

RetrofitServiceModule包括NetworkModule作为其依赖性,因此,NetworkModule.kt

    package com.satincreditcare.satin.android.dagger.module

import android.content.Context
import android.os.Build
import android.util.Base64
import com.satincreditcare.satin.android.R
import com.satincreditcare.satin.android.constants.AppConstants
import com.satincreditcare.satin.android.constants.REST_API
import com.satincreditcare.satin.android.events.AllEvents
import com.satincreditcare.satin.android.events.Event
import com.satincreditcare.satin.android.network.exception.InvalidRefreshTokenException
import com.satincreditcare.satin.android.network.exception.InvalidTokenException
import com.satincreditcare.satin.android.network.exception.NoConnectivityException
import com.satincreditcare.satin.android.dagger.qualifier.LMSApplicationQualifier
import com.satincreditcare.satin.android.dagger.qualifier.LMSAuthQualifier
import com.satincreditcare.satin.android.dagger.scope.LmsAndroidApplicationScope
import com.satincreditcare.satin.android.utils.AppUtility
import com.satincreditcare.satin.android.utils.DataHolder
import com.satincreditcare.satin.android.utils.NetworkUtils
import dagger.Module
import dagger.Provides
import okhttp3.*
import okhttp3.logging.HttpLoggingInterceptor
import org.greenrobot.eventbus.EventBus
import timber.log.Timber
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.nio.charset.Charset
import java.security.KeyStore
import java.security.cert.Certificate
import java.security.cert.CertificateFactory
import java.util.*
import java.util.concurrent.TimeUnit
import javax.net.ssl.*

/**
 * Created by Abhishek Jha on 1/29/2019.
 */

@Module(includes = [(ContextModule::class)])
open class NetworkModule {
    companion object {
        val DEFAULT_READ_TIMEOUT: Long = 180
        val DEFAULT_CONNECT_TIMEOUT: Long = 180
        val maxRequestsPerHost: Int = 5
    }

    @Provides
    @LmsAndroidApplicationScope
    @LMSApplicationQualifier
    fun okHttpClient(interceptorLogging: HttpLoggingInterceptor, cache: Cache,
                              sslSocketFactory: SSLSocketFactory, trustManager: X509TrustManager,
                              @LMSApplicationQualifier interceptor: Interceptor,
                              authenticator: Authenticator): OkHttpClient {
        var okHttpClient: OkHttpClient = OkHttpClient.Builder()
                .sslSocketFactory(sslSocketFactory, trustManager)
                .readTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS)
                .connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .addInterceptor(interceptorLogging)
                .addInterceptor(interceptor)
                .authenticator(authenticator)
                .cache(cache)
                .build()

        if (AppConstants.SLOW_NETWORK_MODE) {
            okHttpClient.dispatcher().maxRequestsPerHost = maxRequestsPerHost / 2
        } else {
            okHttpClient.dispatcher().maxRequestsPerHost = maxRequestsPerHost
        }
        return okHttpClient

    }

    @Provides
    @LmsAndroidApplicationScope
    @LMSAuthQualifier
    fun okHttpClientAuth(interceptorLogging: HttpLoggingInterceptor, cache: Cache,
                                  sslSocketFactory: SSLSocketFactory,
                                  trustManager: X509TrustManager,
                                  @LMSAuthQualifier interceptor: Interceptor): OkHttpClient {
        var okHttpClient: OkHttpClient = OkHttpClient.Builder()
                .sslSocketFactory(sslSocketFactory, trustManager)
                .readTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS)
                .connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .addInterceptor(interceptorLogging)
                .addInterceptor(interceptor)
                .cache(cache)
                .build()
        if (AppConstants.SLOW_NETWORK_MODE) {
            okHttpClient.dispatcher().maxRequestsPerHost = maxRequestsPerHost / 2
        } else {
            okHttpClient.dispatcher().maxRequestsPerHost = maxRequestsPerHost
        }
        return okHttpClient
    }

    @Provides
    @LmsAndroidApplicationScope
    fun x509TrustManager(context: Context): X509TrustManager {
        lateinit var trustManager: X509TrustManager
        try {
            //Load CAs
            val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
            val cert: InputStream

            if (REST_API.getInstance(context).API.equals(context.getString(R.string.PROD_URL),
                            ignoreCase = true)) {
                cert = context.resources.openRawResource(R.raw.prod)
            } else {
                cert = context.resources.openRawResource(R.raw.dev_uat)
            }

            val ca: Certificate
            try {
                ca = cf.generateCertificate(cert)
            } finally {
                cert.close()
            }

            //Creating a keystore containing our trusted CAs
            val keyStoreType: String = KeyStore.getDefaultType()
            val keyStore: KeyStore = KeyStore.getInstance(keyStoreType)
            keyStore.load(null, null)
            keyStore.setCertificateEntry("ca", ca)

            // creating a TrustManager that trusts the CAs in our KeyStore
            val tmfAlgorithm: String = TrustManagerFactory.getDefaultAlgorithm()
            val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm)
            tmf.init(keyStore)

            //X509Trust Manager
            val trustManagers = tmf.trustManagers
            if (trustManagers.size != 1 || trustManagers[0] !is X509TrustManager) {
                throw IllegalStateException("Unexpected default trust managers:" + Arrays
                        .toString(trustManagers))
            }
            trustManager = trustManagers[0] as X509TrustManager
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return trustManager
    }

    @Provides
    @LmsAndroidApplicationScope
    fun sslSocketFactory(trustManager: X509TrustManager): SSLSocketFactory {
        lateinit var sslContext: SSLContext
        lateinit var sslSocketFactory: SSLSocketFactory
        try {
            sslContext = SSLContext.getInstance("SSL")
            sslContext.init(null, arrayOf(trustManager), null)
            sslSocketFactory = sslContext.socketFactory
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return sslSocketFactory
    }

    @Provides
    @LmsAndroidApplicationScope
    fun httpLoggingInterceptor(): HttpLoggingInterceptor {
        val interceptor: HttpLoggingInterceptor = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger {
            Timber.i(it)
        })
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
        return interceptor
    }

    @Provides
    @LmsAndroidApplicationScope
    @LMSAuthQualifier
    fun interceptorAuth(context: Context): Interceptor {
        val interceptor: Interceptor = Interceptor {
            //Applying two interceptors work together
            //Network Interceptor and OAuthTokenInterceptor

            if (NetworkUtils.isNetworkAvailable(context)) {
                //Here, we will check for the SecureHeaderInterceptor start
                val deviceHeader: String = Build.MODEL + "$$" + AppUtility.getImei(context)
                val headerValue: String = Credentials.basic(AppUtility.getOAuthClientId(context),
                        AppUtility.getOAuthClientSecret(context), Charset.forName(AppConstants.CHARSET_UTF8))
                var rawRequest: Request = it.request()
                rawRequest = rawRequest
                        .newBuilder()
                        .addHeader(AppConstants.HTTP_HEADER_AUTHORIZATION, headerValue)
                        .addHeader(AppConstants.HTTP_HEADER_DEVICE_AUTH, AppUtility
                                .encodeBase64(deviceHeader.trim(), Base64.NO_WRAP))
                        .build()

                //Here, we will check for the OAuthTokenInterceptor end

                try {
                    return@Interceptor it.proceed(rawRequest)
                } catch (e: Exception) {
                    e.printStackTrace()
                    throw IOException(e)
                }
            } else {
                throw NoConnectivityException()
            }
        }
        return interceptor
    }

    @Provides
    @LmsAndroidApplicationScope
    @LMSApplicationQualifier
    fun interceptor(context: Context): Interceptor {
        return Interceptor { chain ->
            //Applying two interceptors work together
            //Network Interceptor and OAuthTokenInterceptor
            if (NetworkUtils.isNetworkAvailable(context)) {

                //Here, we will check for the OAuthTokenInterceptor start

                var rawRequest = chain.request()
                //getting token
                if (DataHolder.getInstance() == null) {
                    throw InvalidTokenException()
                }

                val resOAuthToken = DataHolder.getInstance().oauthToken
                        ?: throw InvalidTokenException()

                if (!DataHolder.getInstance().isRefreshingToken) {
                    if (!DataHolder.getInstance().isRefreshTokenExpired) {
                        Timber.i("Sending request")

                        //locally checking life of access token
                        if (System.currentTimeMillis() < resOAuthToken.expiresOn) {
                            if (!AppConstants.IS_CUSTOM_IP) {
                                rawRequest = rawRequest.newBuilder()
                                        .addHeader("Authorization", AppUtility
                                                .createOAuthHeader(resOAuthToken.accessToken))
                                        .build()
                            }
                        } else {
                            //Sending Signal to refresh access token from server
                            DataHolder.getInstance().isRefreshingToken = true
                            EventBus.getDefault().post(Event(AllEvents
                                    .OAUTH_ACCESS_TOKEN_EXPIRED, false, resOAuthToken))
                            //dropping ongoing request(because access_token is expired)
                            throw InvalidTokenException()
                        }
                    } else {
                        //refresh token is expired (user should be logged out
                        throw InvalidRefreshTokenException(context)
                    }
                } else {
                    //access token is getting refreshed so drop this request
                    Timber.i("access toke is already getting refreshed")
                    throw InvalidTokenException()
                }

                //Here, we will check for the OAuthTokenInterceptor end

                //If everything goes well we can proceed to the below statement and satisfy
                // the condition for the Network availability.

                try {
                    return@Interceptor chain.proceed(rawRequest)//chain.request()
                } catch (e: Exception) {
                    e.printStackTrace()
                    throw IOException(e)
                }

            } else {
                throw NoConnectivityException()
            }
            //return chain.proceed(chain.request());
        }
    }

    @Provides
    @LmsAndroidApplicationScope
    fun getAuthenticator(context: Context): Authenticator {
        return Authenticator { route, response ->
            val resOAuthToken = DataHolder.getInstance().oauthToken
            //Checking if access token is getting refreshed.
            if (!DataHolder.getInstance().isRefreshingToken) {
                if (!DataHolder.getInstance().isRefreshTokenExpired) {
                    Timber.i("Now refreshing token")
                    //refreshing access_token from oauth server
                    DataHolder.getInstance().isRefreshingToken = true
                    EventBus.getDefault().post(Event(AllEvents
                            .OAUTH_ACCESS_TOKEN_EXPIRED, false, resOAuthToken))
                } else {
                    //refresh token is expired (user should be logged out
                    throw InvalidRefreshTokenException(context)
                }
            } else {
                Timber.i("already refreshing token")
                //access token is getting refreshed so drop this request
                //throw new InvalidTokenException();
            }
            //we are dropping every request
            throw InvalidTokenException()
        }
    }

    @Provides
    @LmsAndroidApplicationScope
    fun cache(cacheFile: File): Cache {
        return Cache(cacheFile, 10 * 1000 * 1000)
    }

    @Provides
    @LmsAndroidApplicationScope
    fun file(context: Context): File{
        return File(context.cacheDir, "okhttp_cache")
    }

}

而NetworkModule需要ContextModule.kt的依赖

package com.satincreditcare.satin.android.dagger.module

import android.content.Context
import com.satincreditcare.satin.android.dagger.scope.LmsAndroidApplicationScope
import dagger.Module
import dagger.Provides

/**
 * Created by Abhishek Jha on 1/30/2019.
 */

@Module
open class ContextModule(context: Context) {
    private val mContext: Context = context

    @Provides
    @LmsAndroidApplicationScope
    fun context(): Context{
        return mContext
    }

}

和RepositoryModule.kt

package com.satincreditcare.satin.android.dagger.module

import android.arch.lifecycle.ViewModelProvider
import android.content.Context
import com.satincreditcare.satin.android.mvvm.data.AppRepository
import com.satincreditcare.satin.android.mvvm.viewmodel.CustomViewModelFactory
import com.satincreditcare.satin.android.mvvm.viewmodel.CustomViewModelFactoryAuth
import com.satincreditcare.satin.android.network.rest_controller.RestInterface
import com.satincreditcare.satin.android.dagger.qualifier.LMSApplicationQualifier
import com.satincreditcare.satin.android.dagger.qualifier.LMSAuthQualifier
import com.satincreditcare.satin.android.dagger.scope.LmsAndroidApplicationScope
import dagger.Module
import dagger.Provides

/**
 * Created by Abhishek Jha on 1/30/2019.
 */
@Module(includes = [(RetrofitServiceModule::class), (ContextModule::class)])
open class RepositoryModule {

    @Provides
    @LmsAndroidApplicationScope
    @LMSApplicationQualifier
    fun appRepository(@LMSApplicationQualifier restInterface: RestInterface, context: Context): AppRepository{
        return AppRepository(restInterface, context)
    }

    @Provides
    @LmsAndroidApplicationScope
    @LMSApplicationQualifier
    fun provideViewModelFactory(@LMSApplicationQualifier appRepository: AppRepository): ViewModelProvider.Factory{
        return CustomViewModelFactory(appRepository)
    }

    @Provides
    @LmsAndroidApplicationScope
    @LMSAuthQualifier
    fun appRepositoryAuth(@LMSAuthQualifier restInterface: RestInterface, context: Context): AppRepository{
        return AppRepository(restInterface, context)
    }

    @Provides
    @LmsAndroidApplicationScope
    @LMSAuthQualifier
    fun provideViewModelFactoryAuth(@LMSAuthQualifier appRepository: AppRepository): ViewModelProvider.Factory{
        return CustomViewModelFactoryAuth(appRepository)
    }

}

所以,当我得到我的ApplicationComponent在我的应用程序类为:

public class LmsAndroidApplication extends Application {
    public static String TAG = BuildConfig.VERSION_NAME + AppConstants.EMPTY_SPACE;

    public LmsApplicationComponent component;

    public static LmsAndroidApplication get(Activity activity){
        return (LmsAndroidApplication) activity.getApplication();
    }

    public LmsApplicationComponent component(){
        return component;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        //Leak Canary should first be installed.
        /*if(LeakCanary.isInAnalyzerProcess(this)){
            // This process is dedicated to LeakCanary for heap analysis.
            // You should not init your app in this process.
            return;
        }
        LeakCanary.install(this);*/
        //Dagger Basic setup for Api and repository setup
        if(BuildConfig.DEBUG){
            Timber.plant(new Timber.DebugTree());
        }
        component = DaggerLmsApplicationComponent
                .builder()
                .contextModule(new ContextModule(this))
                .build();
}
}

我访问我的片段类作为ApplicationComponent的方法:

@Inject
@LMSApplicationQualifier
lateinit var viewModelFactory: ViewModelProvider.Factory

var lmsApplicationComponent: LmsApplicationComponent = LmsAndroidApplication.get(activity).component()

viewModelFactory = lmsApplicationComponent.provideViewModelFactory()

我曾访问过它没有任何问题,但是当我试图通过片段的组件来访问这同一个对象,它给出了一个失踪绑定错误。请找到碎片的组成部分代码PendPsychoComponent.kt

package com.satincreditcare.satin.android.dagger.component

import com.satincreditcare.satin.android.dagger.module.PendPsychoModule
import com.satincreditcare.satin.android.dagger.scope.PendPsychoScope
import com.satincreditcare.satin.android.pendPsychoMvvm.PendPsychoFragment
import dagger.Component

/**
 * Created by Abhishek Jha on 1/30/2019.
 */
@PendPsychoScope
@Component(dependencies = [(LmsApplicationComponent::class)], modules = [(PendPsychoModule::class)])
interface PendPsychoComponent {

    fun injectPendingPsycho(pendPsychoFragment: PendPsychoFragment)

}

正如你所看到的,我已经addded依赖标签与AppComponent的价值,但我无法访问LmsApplicationComponent的方法,这种方法,但我能够访问它时,我在Java中使用了。请帮我解决这个问题。!提前致谢。

android kotlin dagger-2
1个回答
0
投票

你需要建立你的片段组成部分,并使用你的应用程序组件的依赖。此外,您不需要设置一个实例viewModelFactory匕首会为你做到这一点。

事情是这样的:

DaggerPendPsychoComponent.builder()
            .lmsApplicationComponent(LmsAndroidApplication.get(activity).component())
            .pendPsychoModule(PendPsychoModule())
            .build()
            .inject(this)
© www.soinside.com 2019 - 2024. All rights reserved.