在Fragment中注入依赖项的问题(MVP,Dagger2,Kotlin)

时间:2018-02-17 20:57:54

标签: android kotlin mvp dagger-2

我是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()
}
}

拜托,有人可以帮我解决这个问题吗? 提前谢谢!

0 个答案:

没有答案