简体   繁体   English

在Dagger2上将@Inject用于Android的Fragment是一种好习惯吗?

[英]Is it a good practice to use @Inject for Android's Fragment on Dagger2?

I am using @ContributesAndroidInjector of Dagger 2.11. 我正在使用Dagger 2.11的@ContributesAndroidInjector

It works without problems with the following sources. 使用以下来源,它可以正常工作。
@ActivityScope is also working. @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() {
...

But when I read the document , I felt it was correct to use @ConstructsAndroidInjector as well as activity. 但是,当我阅读该文档时 ,我觉得使用@ConstructsAndroidInjector以及activity都是正确的。

And also in the answer here , it is written as 而且在这里的答案中,它写为

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

Is my implementation problematic? 我的实施有问题吗?
What problems will occur with my implementation? 我的实施会出现什么问题?

Fragments are managed by, well, the FragmentManager in Android. 片段由Android中的FragmentManager管理。

In subclasses of FragmentActivity , including AppCompatActivity , when onSaveInstanceState(Bundle outBundle) is called on your Activity it will save the state of your Fragments. FragmentActivity子类(包括AppCompatActivity ,当在您的Activity上调用onSaveInstanceState(Bundle outBundle) ,它将保存Fragments的状态。

Likewise onCreate(Bundle savedInstanceState) will attempt to restore them. 同样, onCreate(Bundle savedInstanceState)将尝试还原它们。 You can cause this to happen by turning on Developer Options / Don't keep Activities and navigating in and out of your app. 您可以通过打开“ Developer Options / Don't keep Activities并浏览应用程序来实现此目的。

In this situation, if you request injection of your Fragment field again using Dagger 2, the Activity will reference two copies of the Fragment - the restored Fragment and the newly injected one. 在这种情况下,如果您再次请求使用Dagger 2注入Fragment字段,则Activity将引用Fragment的两个副本-还原的Fragment和新注入的Fragment。 You don't want this! 你不要这个! Instead, the correct idiom to get a handle on the Fragment in your onCreate is the following: 相反,以下是在onCreate获取Fragment句柄的正确用法:

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

where MainFragment.instantiate(Bundle args) is a static method in a companion object . 其中MainFragment.instantiate(Bundle args)companion object的静态方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM