gpt4 book ai didi

Android Inject Dependency (Dagger 2) Inside Fragment 使用@ContributesAndroidInjector

转载 作者:搜寻专家 更新时间:2023-11-01 09:25:49 28 4
gpt4 key购买 nike

我正在使用 Dagger 2在我的项目中进行依赖注入(inject)

问题是当我试图在依赖于 FragmentManager 的 fragment 类中注入(inject) ViewPageAdapter 时,如下所示:

@Inject
lateinit var mainTripsFragmentAdapter: MainTripsFragmentAdapter

我收到以下构建错误:

error: [dagger.android.AndroidInjector.inject(T)] android.support.v4.app.FragmentManager cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector { ^ android.support.v4.app.FragmentManager is injected at com.example.presenters.main.trips.MainTripsFragmentAdapter.(fragmentManager, …) com.example.presenters.main.trips.MainTripsFragmentAdapter is injected at com.example.presenters.main.trips.MainTripsFragment.mainTripsFragmentAdapter com.example.presenters.main.trips.MainTripsFragment is injected at com.example.presenters.main.MainActivity.tripsFragment com.example.presenters.main.MainActivity is injected at dagger.android.AndroidInjector.inject(arg0) A binding with matching key exists in component: com.example.di.FragmentBuilder_BindMainTripsFragment$app_debug.MainTripsFragmentSubcomponent

我研究了3天,看了很多文章,都没有弄清楚问题出在哪里!
相关代码我贴出来,如果太长请见谅

需要PagerAdapterFragment:

class MainTripsFragment @Inject constructor() : BaseFragment() {

@Inject
lateinit var mainTripsFragmentAdapter: MainTripsFragmentAdapter

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
pager.adapter = mainTripsFragmentAdapter
}
}

基础 fragment :

abstract class BaseFragment : DaggerFragment() {

override fun onAttach(context: Context?) {
AndroidSupportInjection.inject(this)
super.onAttach(context)
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(getLayout(), container, false)

abstract fun getLayout(): Int
}

这是FragmentPagerAdapter:

class MainTripsFragmentAdapter @Inject constructor(
fragmentManager: FragmentManager,
private val mainCurrentTripsFragment: MainCurrentTripsFragment,
private val mainHistoryTripsFragment: MainHistoryTripsFragment
) : FragmentPagerAdapter(fragmentManager) {

override fun getItem(position: Int) = when (position) {
0 -> mainCurrentTripsFragment
1 -> mainHistoryTripsFragment
else -> mainCurrentTripsFragment
}

override fun getCount() = 2
}

这里是 DI 相关类:

应用组件:

@Singleton
@Component(modules = [
AndroidInjectionModule::class,
ActivityBuilder::class,
FragmentBuilder::class
])

interface AppComponent : AndroidInjector<DaggerApplication> {

fun inject(app: App)

override fun inject(instance: DaggerApplication)

@Component.Builder
interface Builder {
@BindsInstance
fun application(app: Application): Builder

fun build(): AppComponent
}
}

fragment 生成器:

@Module
abstract class FragmentBuilder {

@ContributesAndroidInjector
internal abstract fun bindMainHomeFragment(): MainHomeFragment

@Module
internal interface MainTripsFragmentModule {

@Binds
fun bindMainTripsFragment(fragment: MainTripsFragment): Fragment
}

@ContributesAndroidInjector(modules = [FragmentModule::class, MainTripsFragmentModule::class])
internal abstract fun bindMainTripsFragment(): MainTripsFragment

@ContributesAndroidInjector
internal abstract fun bindMainCurrentTripsFragment(): MainCurrentTripsFragment
@ContributesAndroidInjector
internal abstract fun bindMainHistoryTripsFragment(): MainHistoryTripsFragment
}

fragment 模块:

@Module
class FragmentModule {

@Provides
fun provideFragmentManager(fragment: Fragment) = fragment.childFragmentManager
}

Activity 构建器:

@Module
abstract class ActivityBuilder {

@ContributesAndroidInjector
internal abstract fun contributeMainActivity(): MainActivity
}

主要 Activity :

class MainActivity : BaseActivity() {

@Inject
lateinit var tripsFragment: MainTripsFragment

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

showFragment(tripsFragment)
}

private fun showFragment(fragment: Fragment) {
supportFragmentManager
.beginTransaction()
.replace(R.id.layout_container, fragment)
.commit()
}
}

基础 Activity :

@SuppressLint("Registered")
abstract class BaseActivity : AppCompatActivity(), HasSupportFragmentInjector {

@Inject
lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>

override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
}
override fun supportFragmentInjector() = fragmentInjector
}

应用类:

class App : Application(), HasActivityInjector {
@Inject
lateinit var activityInjector: DispatchingAndroidInjector<Activity>

override fun activityInjector(): AndroidInjector<Activity> = activityInjector

override fun onCreate() {
super.onCreate()

DaggerAppComponent.builder()
.application(this)
.build()
.apply {
inject(this@App)
}

}
}

有一点是,如果我在我的 Activity 中 @Inject PagerAdapter(我也应该为它添加一个模块)它工作正常。
哪一部分实现错误?

最佳答案

这里有很多问题:

class MainTripsFragmentAdapter @Inject constructor(
fragmentManager: FragmentManager,
private val mainCurrentTripsFragment: MainCurrentTripsFragment,
private val mainHistoryTripsFragment: MainHistoryTripsFragment
) : FragmentPagerAdapter(fragmentManager) {

override fun getItem(position: Int) = when (position) {
0 -> mainCurrentTripsFragment //no!!
1 -> mainHistoryTripsFragment
else -> mainCurrentTripsFragment
}

override fun getCount() = 2
}
PagerAdapter 中的

getItem 表示“创建项目”。当您使用 PagerAdapter 时,您会将 fragment 的创建委托(delegate)给适配器。您不应该编写代码来缓存和存储 fragment ,这是 FragmentManager 的工作。

您的 FragmentAdapter 应该看起来像这样:

    override fun getItem(position: Int) = when (position) { 
0 -> MainCurrentTripsFragment.instantiate()
1 -> MainHistoryTripsFragment.instantiate()
else -> MainCurrentTripsFragment.instantiate()
}

instantiate 方法在 fragment 中的伴生对象中声明:

class MainCurrentTripsFragment: Fragment() {
companion object {
@JvmStatic
fun instantiate(args: Bundle?) {
val frag = MainCurrentTripsFragment()
frag.arguments = args
}
}
}

这是在 Android 中使用带有 Fragment 的 PagerAdapter 的标准习惯用法。您不应在对象图中提供 PagerAdapters 或 Fragments 作为依赖项。事实上,许多由操作系统控制的 Android 类,如 FragmentManagerActivityFragmentBroadcastReceiver服务 不是使用 Dagger 2 成为对象图中依赖项的良好候选者。

开始使用 Dagger 2 时的一个常见错误是尝试注入(inject)一切,就好像手动更新任何东西都是错误的一样。这在 Android 中是不可能的。

请从您的模块中取出 Fragments、FragmentManager、PagerAdapter 等。不要尝试使用 Dagger 2 提供或绑定(bind)这些。然后使用 Dagger 2 注入(inject)域层或数据层对象,如存储库、Retrofit 服务等。如果你遇到困难,你可以随时发布另一个问题。

并查看官方 Google Android Architecture blueprints .理想情况下,您的解决方案应该类似于它们。

关于Android Inject Dependency (Dagger 2) Inside Fragment 使用@ContributesAndroidInjector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50781163/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com