【问题标题】:Is it a good practice to use @Inject for Android's Fragment on Dagger2?在 Dagger2 上为 Android 的 Fragment 使用 @Inject 是一个好习惯吗?
【发布时间】:2026-02-04 16:00:02
【问题描述】:

我正在使用 Dagger 2.11 的 @ContributesAndroidInjector

以下来源可以正常工作。
@ActivityScope 也可以正常工作。

class MainActivity : AppCompatActivity(), HasFragmentInjector {
    @Inject
    lateinit var androidInjector: DispatchingAndroidInjector<Fragment>
    override fun fragmentInjector() = androidInjector
    @Inject
    lateinit var fragment: MainFragment
    @Inject
    lateinit var viewModel: MainViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        fragmentManager.beginTransaction()
                .replace(R.id.container, fragment)
                .commitAllowingStateLoss()
        viewModel.start("activity")
    }
}

class MainFragment @Inject constructor() : Fragment() {
    @Inject
    lateinit var viewModel: MainViewModel
    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater!!.inflate(R.layout.fragment_main, container, false)
        return view
    }

    override fun onAttach(context: Context?) {
        super.onAttach(context)
        viewModel.start("fragment")
    }
}

@Module
abstract class AndroidModule {
    @ActivityScope
    @ContributesAndroidInjector
    abstract fun contributeMainActivity(): MainActivity
}

@ActivityScope
class MainViewModel @Inject constructor() {
...

但是当我阅读document时, 我觉得使用@ConstructsAndroidInjector 和活动是正确的。

而且在答案here中,也写成

public class MainActivity {
    @Inject CoffeeFragment coffeeFragment; //no! don't do this
    @Inject TeaFragment teaFragment; //no!

我的实现有问题吗?
我的实施会出现什么问题?

【问题讨论】:

    标签: android android-fragments kotlin dagger-2 dagger


    【解决方案1】:

    片段由 Android 中的 FragmentManager 管理。

    FragmentActivity 的子类中,包括AppCompatActivity,当你的Activity 调用onSaveInstanceState(Bundle outBundle) 时,它会保存你的Fragment 的状态。

    同样onCreate(Bundle savedInstanceState) 将尝试恢复它们。您可以通过打开 Developer Options / Don't keep Activities 并在您的应用中导航进出来实现这一点。

    在这种情况下,如果您再次使用 Dagger 2 请求注入 Fragment 字段,则 Activity 将引用 Fragment 的两个副本 - 恢复的 Fragment 和新注入的 Fragment。你不想要这个!相反,在 onCreate 中处理 Fragment 的正确习惯用法如下:

    fragment = fragmentManager.findFragmentByTag("MAIN")
    if (fragment == null) fragment = MainFragment.instantiate(null)
    fragmentManager.beginTransaction()
                .replace(R.id.container, fragment, "MAIN")
                .commit()
    

    其中MainFragment.instantiate(Bundle args)companion object 中的静态方法。

    【讨论】:

    • 谢谢。我知道有问题。但是在上面的代码中,通过在 Fragment#onAttach 中添加 AndroidInjection.inject(this),Activity 和 Fragment 的 ViewModel 不共享为@ActivityScope。有办法分享吗?
    最近更新 更多