androidbroadcast / ViewBindingPropertyDelegate

Make work with Android View Binding simpler
https://proandroiddev.com/make-android-view-binding-great-with-kotlin-b71dd9c87719
Apache License 2.0
1.42k stars 102 forks source link

BUG ViewBinding crushed inside DialogFragment with AlertDialog #33

Closed P1NG2WIN closed 3 years ago

P1NG2WIN commented 3 years ago

I've got crush Can't access the Fragment View's LifecycleOwner when getView() is null i.e., before onCreateView() or after onDestroyView() when set view to dialog (setView(viewBinding.root))

supportFragmentManager?.let { updateDialog.showDialog(it) } //showDialog

Dialog

class SimpleDialog : BaseDialogFragment(0, null) {

    companion object {
        const val DEF_DIALOG_TAG = "GabiDialog"
        const val canBeCanceled = false
    }

    private val viewBinding: DialogGabiBinding by viewBinding(createMethod = CreateMethod.INFLATE)

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        isCancelable = canBeCanceled

        val dialog = AlertDialog.Builder(requireContext())
            .setView(viewBinding.root)
            .setCancelable(canBeCanceled)
            .create()

        initDialogView(dialog)

        return dialog
    }

    private fun initDialogView(dialog: AlertDialog) {
        viewBinding.dialogTitle.apply {}

        viewBinding.dialogContent.apply {}

        viewBinding.confirmBtn.apply {}

        viewBinding.cancelBtn.apply {}
    }

    fun showDialog(fragmentManager: FragmentManager, tag: String = DEF_DIALOG_TAG) {
        if (fragmentManager.findFragmentByTag(tag) != null)
            (fragmentManager.findFragmentByTag(tag) as? DialogFragment)
                ?.dismiss()

        show(fragmentManager, tag)
    }

}

BaseDialogFragment

abstract class BaseDialogFragment(
    @LayoutRes private val layoutRes: Int,
    private val onDismiss: (() -> Unit)? = null
): DialogFragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Timber.d("Lifecycle - onCreate %s", this.javaClass.name)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return if (layoutRes != 0)
            inflater.inflate(layoutRes, container, false)
        else
            null
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Timber.d("Lifecycle - onViewCreated %s", this.javaClass.name)
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog =  super.onCreateDialog(savedInstanceState)
        Timber.d("Lifecycle - onCreateDialog %s", this.javaClass.name)
        return dialog
    }

    override fun onStart() {
        super.onStart()
        Timber.d("Lifecycle - onStart() %s", this.javaClass.name)
    }

    override fun onStop() {
        super.onStop()
        Timber.d("Lifecycle - onStop() %s", this.javaClass.name)
    }

    override fun onResume() {
        super.onResume()
        Timber.d("Lifecycle - onResume() %s", this.javaClass.name)
    }

    override fun onPause() {
        super.onPause()
        Timber.d("Lifecycle - onPause() %s", this.javaClass.name)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Timber.d("Lifecycle - onDestroyView() %s", this.javaClass.name)
    }

    override fun onDestroy() {
        super.onDestroy()
        Timber.d("Lifecycle - onDestroy() %s", this.javaClass.name)
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        onDismiss?.invoke()
    }

}
P1NG2WIN commented 3 years ago

Works with default viewBinding api


    private var _viewBinding: DialogGabiBinding? = null
    private val viewBinding get() = _viewBinding!!

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        _viewBinding = DialogGabiBinding.inflate(LayoutInflater.from(context))

        isCancelable = canBeCanceled

        val dialog = AlertDialog.Builder(requireContext())
            .setView(viewBinding.root)
            .setCancelable(canBeCanceled)
            .create()

        //initDialogView()

        return dialog
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        initDialogView()

        return viewBinding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _viewBinding = null
    }
kirich1409 commented 3 years ago

Try to use dialogViewBinding instead of viewBinding

P1NG2WIN commented 3 years ago

Try to use dialogViewBinding instead of viewBinding

Did not help. Anyway, i just removed AlertDialog from DialogFragment