我是Android的新手。我尝试通过Dagger2和Kotlin以MVP模式在Fragments上构建项目。 我在构建项目时遇到了错误。
Error:(11, 2) error: com.company.my.ui.users.UsersPresenter<? super com.company.my.ui.users.UsersFragment> cannot be provided without an @Provides- or @Produces-annotated method.
public abstract void inject(@org.jetbrains.annotations.NotNull()
^
com.company.my.ui.users.UsersPresenter<? super com.company.my.ui.users.UsersFragment> is injected at
com.company.my.ui.users.UsersFragment.usersPresenter
com.company.my.ui.users.UsersFragment is injected at
com.company.my.di.component.UsersFragmentComponent.inject(fragment)
以下是我的代码:
@Module
class AppModule(private val app: App, private val baseUrl: String) {
@Provides
@Singleton
fun provideApplication(): Application = app
@Provides
@Singleton
fun provideRetrofit(gson: Gson): Retrofit =
Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
@Provides
@Singleton
fun provideGson(): Gson =
GsonBuilder()
.serializeNulls()
.create()
@Provides
@Singleton
fun provideApiService(retrofit: Retrofit): ApiService = retrofit.create(ApiService::class.java)
@Provides
fun provideCompositeDisposable(): CompositeDisposable = CompositeDisposable()
}
AppComponent
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
fun inject(app: App)
fun apiService(): ApiService
}
MainActivityModule
@Module
class MainActivityModule(private val activity: MainActivity) {
@Provides
fun provideMainActivity(): MainActivity = activity
}
MainActivityComponent
@ActivityScope
@Component(dependencies = [AppComponent::class], modules = [MainActivityModule::class])
interface MainActivityComponent {
fun inject(activity: MainActivity)
}
UsersFragmentModule
@Module
class UsersFragmentModule {
@Provides
fun provideUsersPresenter(service: ApiService, compositeDisposable: CompositeDisposable): UsersContract.UsersPresenter<UsersContract.UsersView>
= UsersPresenter(service, compositeDisposable)
}
UsersFragmentComponent
@ActivityScope
@Component(dependencies = [AppComponent::class], modules = [UsersFragmentModule::class])
interface UsersFragmentComponent {
fun inject(fragment: UsersFragment)
}
Application.class
class App : Application() {
private lateinit var appComponent: AppComponent
companion object {
private lateinit var instance: App
fun get(): App = instance
}
override fun onCreate() {
super.onCreate()
buildGraphAndInject()
}
fun getAppComponent(): AppComponent {
return appComponent
}
fun buildGraphAndInject() {
appComponent = DaggerAppComponent.builder()
.appModule(AppModule(this, ApiConstant.SERVER))
.build()
appComponent.inject(this)
}
}
MainActivity.class
class MainActivity : AppCompatActivity(), UsersFragment.OnDetailFragmentSelectedListener {
companion object {
private const val USER_FRAGMENT_TAG = "user fragment"
fun newIntent(context: Context): Intent =
Intent(context, MainActivity::class.java)
}
private lateinit var mainActivityComponent: MainActivityComponent
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mainActivityComponent = DaggerMainActivityComponent.builder()
.appComponent(App.get().getAppComponent())
.mainActivityModule(MainActivityModule(this))
.build()
mainActivityComponent.inject(this)
replaceFragment(UsersFragment.newInstance())
}
private fun replaceFragment(fragment: Fragment, tag: String = USER_FRAGMENT_TAG) {
supportFragmentManager
.beginTransaction()
.addToBackStack(null)
.replace(R.id.fragmentContainer, fragment, tag)
.commit()
}
}
UsersFragment.class
class UsersFragment : Fragment(), UsersContract.UsersView {
private var listener: OnDetailFragmentSelectedListener? = null
private lateinit var usersAdapter: UsersAdapter
private lateinit var usersComponent: UsersFragmentComponent
@Inject
lateinit var usersPresenter: UsersPresenter<UsersFragment>
companion object {
fun newInstance() = UsersFragment()
}
override fun onAttach(context: Context?) {
super.onAttach(context)
try {
listener = context as OnDetailFragmentSelectedListener
} catch (e: ClassCastException) {
throw ClassCastException(getString(R.string.activity_implementation) + OnDetailFragmentSelectedListener::class.java.simpleName)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
usersComponent = DaggerUsersFragmentComponent.builder()
.appComponent(App.get().getAppComponent())
.usersFragmentModule(UsersFragmentModule())
.build()
usersComponent.inject(this)
usersPresenter.onAttach(this)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_users, container, false)
usersAdapter = UsersAdapter(ArrayList(), { listener?.onDetailFragmentSelected(it) })
with(view) {
recyclerUsers.adapter = usersAdapter
recyclerUsers.layoutManager = LinearLayoutManager(activity)
recyclerUsers.setHasFixedSize(true)
}
usersPresenter.loadUsers()
return view
}
override fun onUsersLoaded(users: List<User>) {
usersAdapter.addUsers(users)
usersAdapter.notifyDataSetChanged()
}
override fun onError(message: String) {
showAlert(message)
}
override fun onDetach() {
super.onDetach()
usersPresenter.onDetach()
listener = null
}
interface OnDetailFragmentSelectedListener {
fun onDetailFragmentSelected(user: User)
fun onCloseAppSelected()
}
}
拜托,有人可以帮我解决这个问题吗? 提前谢谢!