Android Dagger 2在活动中注入DialogUtils类
我正在尝试将我的Android Dagger 2在活动中注入DialogUtils类,android,kotlin,android-alertdialog,dagger-2,Android,Kotlin,Android Alertdialog,Dagger 2,我正在尝试将我的DialogUtils类注入我的LoginActivity,该类在其构造函数中需要活动上下文。下面的代码正在工作,但我只是初始化对话框utils,而不是注入它 DialogUtils.kt class DialogUtils constructor(context: Context) { private val dialog: AlertDialog init { dialog = AlertDialog.Builder(context)
DialogUtils
类注入我的LoginActivity
,该类在其构造函数中需要活动上下文。下面的代码正在工作,但我只是初始化对话框utils
,而不是注入它
DialogUtils.kt
class DialogUtils constructor(context: Context) {
private val dialog: AlertDialog
init {
dialog = AlertDialog.Builder(context)
.setPositiveButton(R.string.ok) { dialog, _ ->
dialog.dismiss()
}
.create()
}
fun showDialog(title: String, msg: String) {
dialog.setTitle(title)
dialog.setMessage(msg)
dialog.show()
}
fun clear() {
if (dialog.isShowing) {
dialog.dismiss()
}
}
}
LoginActivity.kt
class LoginActivity : DaggerAppCompatActivity() {
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
private val loginViewModel by lazy {
ViewModelProviders.of(this, viewModelFactory).get(LoginViewModel::class.java)
}
private lateinit var dialogUtils: DialogUtils
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
dialogUtils = DialogUtils(this)
}
override fun onPause() {
super.onPause()
dialogUtils.clear()
}
}
我想做的是在我的
LoginActivity
中插入dialogUtils:dialogUtils,但为此我需要活动上下文。请记住,DialogUtils
在许多活动中都使用,我如何才能做到这一点。您的设计中有一个缺陷,它与DI或Dagger甚至无关:您的DialogUtils
类将使用普通的AlertDialog
而不是DialogFragment
s。这意味着类生成的对话框不会在屏幕上持久显示(例如,在活动重新启动期间,如设备旋转时),这会给用户带来不好的体验
因此,我要做的是编写一个自定义的AlertDialogFragment
实现,它通过回调与主机通信(可能是活动
或片段
),这意味着,如果您的对话框片段实现找到了一个实现其回调并返回用户操作(如按钮单击等)的主机,它将在某些地方进行查找。这是我在项目中为此目的通常使用的一些实用程序代码:
inline fun <reified T> Fragment.requireCallback(): T =
findCallback() ?: error("No parent / target found or parent / target does not implement " + T::class.java)
inline fun <reified T> Fragment.findCallback(): T? {
val callback: Any? = parentFragment ?: targetFragment ?: context
return callback as? T
}
现在,当您在父级Activity
或Fragment
中实例化对话框时,您只需让该父级实现AlertDialogFragment.Listener
界面,然后将其结果转发给您的ViewModel
——好处是:这将在活动重新启动时起作用
您可能想知道是否需要在主机上为每个对话框实现回调;我的个人规则是:对于主要确认操作的单键对话框(如错误对话框),我不要求回调存在(即使用普通的
findCallback()
),而对于具有多个按钮可单击的特殊DecisionDialogFragment
实现,我通常需要回调,因此,如果没有在主机上实现回调,我的应用程序实际上会崩溃,因为这通常意味着我缺少一段代码。您可以将LoginActivity
(以及所有其他)绑定为模块中的上下文
,然后将该模块添加到用于注入活动的组件中。然后,您的UTIL可以毫无问题地插入/使用上下文
e、 g.在您的登录模块中
@Module
interface LoginModule {
@Binds
bindActivityContext(activity: Context) : Context
}
…然后将模块添加到组件中
@(Sub)Component(modules=[..., LoginModule::class])
interface LoginComponent {
// ...
}
如果已经绑定了一个上下文,则可以使用@Named(..)
或任何其他限定符注释绑定另一个上下文。您还可以直接将其绑定为活动
@(Sub)Component(modules=[..., LoginModule::class])
interface LoginComponent {
// ...
}