我找到了几个相关的主题,但是没有为我的问题找到任何合适的解决方案。我需要提供两个具有不同基本URL的改造实例。这是我的ApiModule.kt:
@AppScope
@Module
internal class ApiModule{
@AppScope
@Provides
fun provideOkHttpClient(): OkHttpClient {
var b = OkHttpClient.Builder()
if (BuildConfig.DEBUG){
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BODY
b.addInterceptor(logging)
}
val t = 60*1000L
b.readTimeout(t, TimeUnit.MILLISECONDS)
b.writeTimeout(t, TimeUnit.MILLISECONDS)
b.connectTimeout(t, TimeUnit.MILLISECONDS)
return b.build()
}
@AppScope
@Provides
fun provideRetrofitAdapter(ok: OkHttpClient): Retrofit {
return Retrofit.Builder()
.client(ok)
.baseUrl(Constants.Api.Links.BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@AppScope
@Provides
fun provideEnergoApi(r: Retrofit): EnergoApi {
return r.create(EnergoApi::class.java)
}
@AppScope
@Provides
fun provideEnergoManager(p: PrefHelper, ea: EnergoApi, pm:PayHubManager): DtecManager {
return DtecManager(p, ea, pm)
}
}
这是我的InfoMudule.kt:
@ActivityScope
@Module
internal class InfoModule{
@ActivityScope
@Provides
fun provideInfoPresenter(p:PrefHelper, d:DtecManager, pu: PushManager, v:ViewUtil, n:NetworkUtil,
a:ApiErrorHandler):InfoPresenter{
return InfoPresenter(p, d, pu, v, n,a)
}
@ActivityScope
@Provides
@Named("Retrofit2")
fun providePushRetrofitAdapter(ok: OkHttpClient): Retrofit {
return Retrofit.Builder()
.client(ok)
.baseUrl(Constants.Api.Links.BASE_PUSH_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@ActivityScope
@Provides
fun providePushApi(r: Retrofit): PushApi {
return r.create(PushApi::class.java)
}
@ActivityScope
@Provides
fun providePushManager(c: Context, p:PrefHelper, pa: PushApi): PushManager {
return PushManager(c,p,pa)
}
}
我的AppComponent:
@AppScope
@Component(modules = arrayOf(AppModule::class, ApiModule::class))
internal interface AppComponent{
fun inject(a:BaseActivity)
fun createLoginActivityComponent(): LoginComponent
fun createInfoComponent(): InfoComponent
fun createPayComponent(): PayComponent
fun createNfcScanComponent(): NfcScanComponent
fun createSettingsComponent(): SettingsComponent
fun getNfcAdapter():NfcAdapter?
}
这是我的InfoComponent:
@ActivityScope
@Subcomponent(modules = arrayOf(InfoModule::class))
internal interface InfoComponent {
fun injectInfoActivity(a: InfoActivity)
}
我的PushApi界面:
internal interface PushApi {
@POST(Links.Push.subscribe)
fun subscribeToPush(@Header ("Content-type: application/json")
@Body b: BodySubscribe): Observable<Response<UniqueKey>>
}
我的InfoActivity:
internal class InfoActivity : BaseActivity(), InfoView, SwipeRefreshLayout.OnRefreshListener {
@Inject lateinit var presenter: InfoPresenter
@Inject lateinit var viewUtil: ViewUtil
companion object {
@JvmStatic val PUT_COUNTERS = 101
@JvmStatic val PAYMENT = 202
@JvmStatic val NAME = "name"
@JvmStatic val CURRENT_COUNTER = "currentCounter"
}
private var accountsDialog: AccountsDialog? = null
private var amountDialog: AmountDialog? = null
private lateinit var date: TextView
private lateinit var usedEnergy: TextView
private lateinit var balance: TextView
private lateinit var balanceTitle: TextView
private lateinit var counter1: TextView
private lateinit var counter1Title: TextView
private lateinit var counter2: TextView
private lateinit var counter2Title: TextView
private lateinit var counter3: TextView
private lateinit var counter3Title: TextView
private lateinit var address: TextView
private lateinit var tariff: TextView
private lateinit var refreshView: SwipeRefreshContainer
private var accountsMenuItem: MenuItem? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
setContentView(R.layout.activity_info)
val toolbar = findViewById(R.id.toolbar) as Toolbar
setSupportActionBar(toolbar)
date = findViewById(R.id.activityInfo_tv_date) as TextView
usedEnergy = findViewById(R.id.activityInfo_tv_used) as TextView
balance = findViewById(R.id.activityInfo_tv_balance) as TextView
balanceTitle = findViewById(R.id.activityInfo_tv_balanceTitle) as TextView
counter1 = findViewById(R.id.activityInfo_tv_counter1) as TextView
counter1Title = findViewById(R.id.activityInfo_tv_counter1Title) as TextView
counter2 = findViewById(R.id.activityInfo_tv_counter2) as TextView
counter2Title = findViewById(R.id.activityInfo_tv_counter2Title) as TextView
counter3 = findViewById(R.id.activityInfo_tv_counter3) as TextView
counter3Title = findViewById(R.id.activityInfo_tv_counter3Title) as TextView
address = findViewById(R.id.activityInfo_tv_address) as TextView
tariff = findViewById(R.id.activityInfo_tv_tariff) as TextView
refreshView = findViewById(R.id.activityInfo_srl) as SwipeRefreshContainer
with(refreshView) {
setOnRefreshListener(this@InfoActivity)
setColorSchemeColors(ContextCompat.getColor(this@InfoActivity, R.color.colorAccent),
ContextCompat.getColor(this@InfoActivity, R.color.colorPrimaryDark))
}
checkComponent(savedInstanceState)
presenter.attachView(this)
presenter.subscribeToPush()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PUT_COUNTERS && resultCode == Activity.RESULT_OK) {
updateInfoView()
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.info_menu, menu)
accountsMenuItem = menu.findItem(R.id.action_accounts)
return true
}
override fun onBackPressed() {
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
R.id.action_logout -> presenter.onLogOutClicked()
R.id.action_accounts -> presenter.onAccountsClicked()
R.id.action_feedback -> navigator.goToFeedbackView(this, presenter.dtecManager.accountInfo.full_name,
presenter.dtecManager.accountInfo.abcode)
R.id.action_settings -> navigator.goToSetingsActivity(this)
}
return super.onOptionsItemSelected(item)
}
override fun onRefresh() {
presenter.onUpdateAccount()
}
override fun isSessionActive(): Boolean {
return checkActiveSession()
}
override fun initComponent() {
App.instance.createInfoComponent().injectInfoActivity(this)
}
override fun activityIsFinishing() {
presenter.detachView()
accountsDialog?.onDestroy()
amountDialog?.onDestroy()
App.instance.releaseInfoComponent()
}
}
我的InfoPresenter:
internal class InfoPresenter(
var prefHelper: PrefHelper,
val dtecManager: DtecManager,
val pushManager: PushManager,
val viewUtils: ViewUtil,
val networkUtil: NetworkUtil,
private var apiErrorHandler: ApiErrorHandler
) : BasePresenter<InfoView>(), AccountsDialog.OnAccountDialogListener {
private var context: Context = App.instance.applicationContext
private var stringTokenizer: StringTokenizer? = null
private var getNewAccountInfoSubscription: Subscription? = null
private var uniqueKey: Observable<UniqueKey>? = null
private lateinit var simpleDateFormat: SimpleDateFormat
private lateinit var addressTitle: String
private lateinit var tariffTitle: String
lateinit var accountInfo: AccountInfo
private set
override fun attachView(mvpView: InfoView) {
super.attachView(mvpView)
addressTitle = context.getString(R.string.activityInfo_tv_addressTitle)
tariffTitle = context.getString(R.string.activityInfo_tv_tariffTitle)
var locale: Locale
when (Locale.getDefault().country) {
"RU" -> locale = Locale("ru")
else -> locale = Locale("uk")
}
simpleDateFormat = SimpleDateFormat("dd MMMM yyyy", locale)
mvpView.updateInfoView()
}
override fun detachView() {
super.detachView()
getNewAccountInfoSubscription?.unsubscribe()
}
override fun onNewAccountSelect(abcode: String?) {
if (mvpView!!.isSessionActive()) {
abcode?.let {
getNewAccountInfo(it)
mvpView?.showLoadingDialog(true)?.subscribe {
getNewAccountInfoSubscription?.unsubscribe()
}
}
}
}
fun subscribeToPush() {
accountInfo = prefHelper.getAccountInfo()
uniqueKey = pushManager.subscribe(Constants.ACCOUNT_TYPE, accountInfo.abcode, accountInfo.unitId, Constants.FIREBASE_KEY)
}
fun onUpdateAccount() {
if (mvpView!!.isSessionActive()) {
if (networkUtil.isOnline(true)) {
getNewAccountInfo(dtecManager.accountInfo.abcode)
} else {
mvpView?.finishRefreshView()
}
}
}
fun onPayClicked(v: View) {
checkViewAttached()
viewUtils.freeze(v)
if (mvpView!!.isSessionActive() && networkUtil.isOnline(true)) {
mvpView?.showAmountDialog()
}
}
}
启动InfoActivity时,应用程序崩溃,错误为“找到多个翻新注释,仅允许一个”。为什么它不提供InfoModule的改造?
答案 0 :(得分:2)
使用qualifiers
,以便Dagger能够知道每种情况应提供哪个Retrofit
实例。
1)创建限定符
RetrofitApi.kt
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class RetrofitApi
RetrofitInfo.kt
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class RetrofitInfo
2)使用限定符
ApiModule.kt
@AppScope
@Provides
@RetrofitApi
fun provideRetrofitAdapter(ok: OkHttpClient): Retrofit {
return Retrofit.Builder()
.client(ok)
.baseUrl(Constants.Api.Links.BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@AppScope
@Provides
fun provideEnergoApi(@RetrofitApi r: Retrofit): EnergoApi {
return r.create(EnergoApi::class.java)
}
InfoModule.kt
@ActivityScope
@Provides
@RetrofitInfo
fun providePushRetrofitAdapter(ok: OkHttpClient): Retrofit {
return Retrofit.Builder()
.client(ok)
.baseUrl(Constants.Api.Links.BASE_PUSH_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@ActivityScope
@Provides
fun providePushApi(@RetrofitInfo r: Retrofit): PushApi {
return r.create(PushApi::class.java)
}