当前位置: 首页 > 知识库问答 >
问题:

Android使用@contributesandroidinjector在片段内注入依赖项(Dagger2)

暴乐邦
2023-03-14
@Inject
lateinit var mainTripsFragmentAdapter: MainTripsFragmentAdapter

我得到以下生成错误:

错误:[dagger.android.androidinjector.inject(T)]没有@provides-annotated方法,无法提供android.support.v4.app.fragmentManager。
公共抽象接口AppComponent扩展dagger.android.androidinjector{^android.support.v4.app.fragmentManager在com.example.presenters.main.trips.maintrips.fragmentManager注入。(fragmentManager,example.presenters.main.mainactivity.tripsfragment com.example.presenters.main.mainactivity在dagger.android.androidinjector.inject(arg0)组件中存在具有匹配键的绑定:com.example.di.fragmentbuilder_bindmaintRipsfragment$app_debug.maintRipsfragmentsubcomponent

我研究了3天,看了很多文章,但我不知道问题出在哪里!
我会发布相关代码,如果太长了,对不起

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

    @Inject
    lateinit var mainTripsFragmentAdapter: MainTripsFragmentAdapter

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

BaseFragment:

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
    }
}
@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
}
@Module
class FragmentModule {

    @Provides
    fun provideFragmentManager(fragment: Fragment) = fragment.childFragmentManager
}
@Module
abstract class ActivityBuilder {

    @ContributesAndroidInjector
    internal abstract fun contributeMainActivity(): MainActivity
}
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()
     }
 }

BaseActivity:

@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)
                }

    }
}

其中一点是,如果我在活动中@injectPagerAdapter(我还应该为它添加一个模块),它工作得很好。
哪个部分实现错误?

共有1个答案

申阳伯
2023-03-14

这里有一些问题:

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
}

getitemPagerAdapter中表示“创建项”。当您使用PagerAdapter时,您将片段的创建委托给适配器。您不应该编写代码来缓存和存储片段,这是fragmentManager的工作。

相反,您的fragmentadapter应该如下所示:

    override fun getItem(position: Int) = when (position) { 
        0 -> MainCurrentTripsFragment.instantiate()
        1 -> MainHistoryTripsFragment.instantiate()
        else -> MainCurrentTripsFragment.instantiate()
    }
class MainCurrentTripsFragment: Fragment() {
    companion object {
        @JvmStatic
        fun instantiate(args: Bundle?) {
            val frag = MainCurrentTripsFragment()
            frag.arguments = args
        }
    }
}
 类似资料:
  • 我正在通过添加CDI重构旧模块。 我以 和 为了进行测试,我创建了一个文件: 为了测试它,我正在做这个博客中显示的 和 现在,当我试图测试逻辑时,我做到了 当我运行它时,两个测试属性都是inject,但是我得到了NPE,因为实例中的属性没有被赋值。 为什么Weld不能识别中的属性? JDK 7,焊接2.2.10,Junit 4.12 更新:发布问题后,开始尝试一个更简单、全新的项目(只有两个接口和

  • 我想在使用guice实例化子类时,将依赖项注入父类。在下面的示例中,我试图创建的一个实例,同时希望能够在运行时使用Guice注入。我该怎么做?

  • 我在一个独立的java项目中使用WELD SE,在我开始使用producers之前,它似乎工作得很好。 生产者方法是有效的——容器使用它,但从不注入产生的bean的内部依赖关系。当我删除生产者时,它正常工作。即使在规范和谷歌上搜索了很长时间,我也找不到原因。 制作人的例子: LaminavalidOr正常注入,但其内部属性(标记为@Inject)未被注入。这个项目有很多优点。带有bean disc

  • 我已经使用GoogleGuice几个月了。我对它很满意,但似乎我用错了。我创造了很多辅助注射,有时还有两个注射器。 因此,我想了解这里的一般原则。 是否应该为连接主类所有内容的所有应用程序配备一个喷油器? 最佳实践是关于从应用程序一开始就尝试在构造函数中注入大量内容吗?(我看到了测试的优势) 我的主要问题是,有时我觉得某些对象组的创建属于某个组件。有必要封装它吗?你会如何处理? 当您拥有一个重要的

  • 问题内容: 如何在不使用调用的情况下使用Spring将依赖项注入? 问题答案: 由于Servlet 3.0 ServletContext具有“ addListener”方法,因此可以通过如下代码添加而不是在web.xml文件中添加侦听器: 这意味着你可以正常地注入“ MyHttpSessionListener”中,并且,只要你的应用程序上下文中存在bean,就会使侦听器注册到容器中

  • 问题内容: 使用ui.router,我们有一个状态控制器: 注册于: 我们遇到了一种情况,我们希望将此控制器作为模板的一部分重复使用: 但是似乎没有一种简单的方法来注入带有正确ID的模拟$ stateParams对象。就像是: 除了编写增强ng-controller的自定义指令或重构我们的代码以利用继承的作用域之外,还有没有现成的方法可以做到这一点? 问题答案: 我不认为有开箱即用的方法。仅使用常