Hilt:自动获取 Fragment LifecycleOwner 和上下文
Hilt: Get Fragment LifecycleOwner and context automagically
我想在将依赖项注入片段时自动获取片段上下文和 lifecycleOwner(例如此处的 viewLifecycleOwner)。我的问题是,该怎么做,因为没有对应的@FragmentContext,就像有@ActivityContext 一样。此外,我想为这个依赖项动态分配一个变量。
我的依赖
class LoginDialog(
context: Context, // get this from fragment
private val mLifecycleOwner: LifecycleOwner, // get this from fragment
private val loginTitle: LoginTitle, // define this when injecting
) : AlertDialog(context, R.style.LoginDialogTheme) {
private var _binding: LoginLoadingScreenBinding? = null
private val binding: LoginLoadingScreenBinding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
initDialog()
super.onCreate(savedInstanceState)
}
override fun show() {
if (isShowing) return
_binding = LoginLoadingScreenBinding.inflate(layoutInflater).apply { lifecycleOwner = mLifecycleOwner }
super.show()
}
override fun dismiss() {
_binding = null
super.dismiss()
}
/**
* Calls show internally
*/
fun onChangeIndicator(mText: String) {
show()
binding.indicator = mText
}
private fun initDialog() {
setTitle(loginTitle.title)
setCancelable(false)
setView(binding.root)
}
sealed class LoginTitle(@StringRes val title: Int) {
object Login : LoginTitle(R.string.loading_login_title)
object Registration : LoginTitle(R.string.loading_registration_title)
object ChangingEmail : LoginTitle(R.string.user_data_changing_email)
}
}
注射
@AndroidEntryPoint
class FragmentA : Fragment() {
// here, context is requireContext(),
// lifecycleOwner is viewLifecylceOwner
// and loginTitle is LoginDialog.LoginTitle.Login
@Inject
@LoginTitleLogin
lateinit var loginDialog: LoginDialog
}
好的,我已经通过创建一个刀柄模块并稍微更改构造函数来解决这个问题,这是解决方案:
依赖关系
class LoginDialog(
private val fragment: Fragment,
private val loginTitle: LoginTitle,
) : AlertDialog(fragment.requireContext(), R.style.LoginDialogTheme) {
private var _binding: LoginLoadingScreenBinding? = null
private val binding: LoginLoadingScreenBinding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
initDialog()
super.onCreate(savedInstanceState)
}
override fun show() {
if (isShowing) return
_binding = LoginLoadingScreenBinding.inflate(layoutInflater).apply { lifecycleOwner = fragment.viewLifecycleOwner }
super.show()
}
override fun dismiss() {
_binding = null
super.dismiss()
}
/**
* Calls show internally
*/
fun onChangeIndicator(mText: String) {
show()
binding.indicator = mText
}
private fun initDialog() {
setTitle(loginTitle.title)
setCancelable(false)
setView(binding.root)
}
sealed class LoginTitle(@StringRes val title: Int) {
object Login : LoginTitle(R.string.loading_login_title)
object Registration : LoginTitle(R.string.loading_registration_title)
object ChangingEmail : LoginTitle(R.string.user_data_changing_email)
}
}
模块
@Module
@InstallIn(FragmentComponent::class)
object FragmentModule {
@LoginTitle
@Provides
fun provideLoginDialogWithLoginTitle(fragment: Fragment) = LoginDialog(
fragment,
LoginDialog.LoginTitle.Login
)
@RegistrationTitle
@Provides
fun provideLoginDialogWithRegistrationTitle(fragment: Fragment) = LoginDialog(
fragment,
LoginDialog.LoginTitle.Registration
)
@ChangingEmailTitle
@Provides
fun provideLoginDialogWithChangingEmailTitle(fragment: Fragment) = LoginDialog(
fragment,
LoginDialog.LoginTitle.ChangingEmail
)
}
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class LoginTitle
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class RegistrationTitle
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class ChangingEmailTitle
用法
@AndroidEntryPoint
class MyFragment : Fragment() {
@Inject
@LoginTitle
lateinit var loginDialog: LoginDialog
}
我想在将依赖项注入片段时自动获取片段上下文和 lifecycleOwner(例如此处的 viewLifecycleOwner)。我的问题是,该怎么做,因为没有对应的@FragmentContext,就像有@ActivityContext 一样。此外,我想为这个依赖项动态分配一个变量。
我的依赖
class LoginDialog(
context: Context, // get this from fragment
private val mLifecycleOwner: LifecycleOwner, // get this from fragment
private val loginTitle: LoginTitle, // define this when injecting
) : AlertDialog(context, R.style.LoginDialogTheme) {
private var _binding: LoginLoadingScreenBinding? = null
private val binding: LoginLoadingScreenBinding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
initDialog()
super.onCreate(savedInstanceState)
}
override fun show() {
if (isShowing) return
_binding = LoginLoadingScreenBinding.inflate(layoutInflater).apply { lifecycleOwner = mLifecycleOwner }
super.show()
}
override fun dismiss() {
_binding = null
super.dismiss()
}
/**
* Calls show internally
*/
fun onChangeIndicator(mText: String) {
show()
binding.indicator = mText
}
private fun initDialog() {
setTitle(loginTitle.title)
setCancelable(false)
setView(binding.root)
}
sealed class LoginTitle(@StringRes val title: Int) {
object Login : LoginTitle(R.string.loading_login_title)
object Registration : LoginTitle(R.string.loading_registration_title)
object ChangingEmail : LoginTitle(R.string.user_data_changing_email)
}
}
注射
@AndroidEntryPoint
class FragmentA : Fragment() {
// here, context is requireContext(),
// lifecycleOwner is viewLifecylceOwner
// and loginTitle is LoginDialog.LoginTitle.Login
@Inject
@LoginTitleLogin
lateinit var loginDialog: LoginDialog
}
好的,我已经通过创建一个刀柄模块并稍微更改构造函数来解决这个问题,这是解决方案:
依赖关系
class LoginDialog(
private val fragment: Fragment,
private val loginTitle: LoginTitle,
) : AlertDialog(fragment.requireContext(), R.style.LoginDialogTheme) {
private var _binding: LoginLoadingScreenBinding? = null
private val binding: LoginLoadingScreenBinding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
initDialog()
super.onCreate(savedInstanceState)
}
override fun show() {
if (isShowing) return
_binding = LoginLoadingScreenBinding.inflate(layoutInflater).apply { lifecycleOwner = fragment.viewLifecycleOwner }
super.show()
}
override fun dismiss() {
_binding = null
super.dismiss()
}
/**
* Calls show internally
*/
fun onChangeIndicator(mText: String) {
show()
binding.indicator = mText
}
private fun initDialog() {
setTitle(loginTitle.title)
setCancelable(false)
setView(binding.root)
}
sealed class LoginTitle(@StringRes val title: Int) {
object Login : LoginTitle(R.string.loading_login_title)
object Registration : LoginTitle(R.string.loading_registration_title)
object ChangingEmail : LoginTitle(R.string.user_data_changing_email)
}
}
模块
@Module
@InstallIn(FragmentComponent::class)
object FragmentModule {
@LoginTitle
@Provides
fun provideLoginDialogWithLoginTitle(fragment: Fragment) = LoginDialog(
fragment,
LoginDialog.LoginTitle.Login
)
@RegistrationTitle
@Provides
fun provideLoginDialogWithRegistrationTitle(fragment: Fragment) = LoginDialog(
fragment,
LoginDialog.LoginTitle.Registration
)
@ChangingEmailTitle
@Provides
fun provideLoginDialogWithChangingEmailTitle(fragment: Fragment) = LoginDialog(
fragment,
LoginDialog.LoginTitle.ChangingEmail
)
}
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class LoginTitle
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class RegistrationTitle
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class ChangingEmailTitle
用法
@AndroidEntryPoint
class MyFragment : Fragment() {
@Inject
@LoginTitle
lateinit var loginDialog: LoginDialog
}