Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/191.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Dagger 2在活动中注入DialogUtils类_Android_Kotlin_Android Alertdialog_Dagger 2 - Fatal编程技术网

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 {
  // ...
}