what is the safe way to show old-style android dia...
# compose
d
what is the safe way to show old-style android dialog from Composable function? For example:
Copy code
@Composable
fun ScreenContent(state: State) {
  if (state.showDialog) {
    // Need to show MaterialDatePicker here
  }
}
Use
SideEffect
?
z
DisposableEffect would probably be more useful.
Copy code
if (state.showDialog) {
  DisposableEffect(dialogDetails) {
    // create dialog, call .show()
    onDispose {
      // Dismiss dialog
    }
  }
}
d
great, thank you!
a
I did the same thing in my app. Here's what I end up with.
Copy code
if (showDialog) {
    val fragmentManager = (LocalContext.current as? FragmentActivity)?.supportFragmentManager
    DisposableEffect(fragmentManager) {
        var datePicker: MaterialDatePicker<*>? = null
        if (fragmentManager != null) {
            datePicker = MaterialDatePicker.Builder.datePicker()
                .setTitleText(title)
                .build()
                .apply {
                    addOnPositiveButtonClickListener {
                        date = it
                    }
                    addOnDismissListener { showDialog = false }
                    show(fragmentManager, javaClass.name)
                }
        }
        onDispose {
            datePicker?.dismiss()
        }
    }
}
2
🙏 2
d
Does this work on rotate for you? I am getting the following exception
Copy code
Process: co.well.wellapp.debug, PID: 4520
    java.lang.RuntimeException: Unable to destroy activity {co.well.wellapp.debug/co.well.wellapp.MainActivity}: java.lang.IllegalStateException: Fragment MaterialDatePicker{c8eff96} (f936d2d6-a3f8-4cfb-bbfc-705fbbe0d273) not associated with a fragment manager.
        at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:5111)
        at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:5140)
        at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5432)
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5362)
        at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.IllegalStateException: Fragment MaterialDatePicker{c8eff96} (f936d2d6-a3f8-4cfb-bbfc-705fbbe0d273) not associated with a fragment manager.
        at androidx.fragment.app.Fragment.getParentFragmentManager(Fragment.java:1059)
        at androidx.fragment.app.DialogFragment.dismissInternal(DialogFragment.java:352)
        at androidx.fragment.app.DialogFragment.dismiss(DialogFragment.java:309)
        at co.well.wellapp.views.compose.WellDatePickerDialogKt$WellDatePickerDialog$2$invoke$$inlined$onDispose$1.dispose(Effects.kt:484)
        at androidx.compose.runtime.DisposableEffectImpl.onForgotten(Effects.kt:85)
        at androidx.compose.runtime.CompositionImpl$RememberEventDispatcher.dispatchRememberObservers(Composition.kt:793)
        at androidx.compose.runtime.CompositionImpl.dispose(Composition.kt:496)
        at androidx.compose.ui.platform.WrappedComposition.dispose(Wrapper.android.kt:171)
        at androidx.compose.ui.platform.AbstractComposeView.disposeComposition(ComposeView.android.kt:266)
        at androidx.compose.ui.platform.ViewCompositionStrategy$DisposeOnDetachedFromWindow$installFor$listener$1.onViewDetachedFromWindow(ViewCompositionStrategy.android.kt:78)
        at android.view.View.dispatchDetachedFromWindow(View.java:20550)
        at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3942)
        at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3934)
        at android.view.ViewGroup.removeViewInternal(ViewGroup.java:5560)
        at android.view.ViewGroup.removeViewInternal(ViewGroup.java:5531)
        at android.view.ViewGroup.removeView(ViewGroup.java:5462)
        at androidx.fragment.app.FragmentContainerView.removeView(FragmentContainerView.kt:288)
        at androidx.fragment.app.SpecialEffectsController$Operation$State.applyState(SpecialEffectsController.java:470)
        at androidx.fragment.app.SpecialEffectsController$1.run(SpecialEffectsController.java:211)
        at androidx.fragment.app.SpecialEffectsController$Operation.complete(SpecialEffectsController.java:713)
        at androidx.fragment.app.SpecialEffectsController$FragmentStateManagerOperation.complete(SpecialEffectsController.java:770)
        at androidx.fragment.app.SpecialEffectsController$Operation.cancel(SpecialEffectsController.java:615)
        at androidx.fragment.app.SpecialEffectsController.forceCompleteAllOperations(SpecialEffectsController.java:350)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2844)
        at androidx.fragment.app.FragmentManager.dispatchDestroy(FragmentManager.java:2820)
        at androidx.fragment.app.FragmentController.dispatchDestroy(FragmentController.java:345)
        at androidx.fragment.app.FragmentActivity.onDestroy(FragmentActivity.java:306)
2022-08-03 22:06:53.084 4520-4520/co.well.wellapp.debug E/AndroidRuntime:     at androidx.appcompat.app.AppCompatActivity.onDestroy(AppCompatActivity.java:278)
        at android.app.Activity.performDestroy(Activity.java:8239)
        at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1344)
        at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:5096)
        	... 13 more
d
Hmm, I didn't check at the time as rotation was "locked" into portrait for that app I was working on...
d
word - just a heads up to anyone looking at this solution in the future!
I put in a feature request for this on the material components repo if anyone would like to star it! https://github.com/material-components/material-components-android/issues/2895
a
That repo contains only the view implementations of material components. Feature requests for Compose should be filed in the google issue tracker, the link of which is in the channel description. Also there is already a feature request for this.
d
Thank you - coworker helped me find that previous issue
And I also logged a dupe 😛
I just removed the
dismiss()
call in
onDispose
so that it doesn't crash
a
You can just catch the exception.
Or let compose handle orientation change (i.e. disable activity recreation) as I'm doing in my app.
s
Which of course comes with its own complexity (read thread), so only do so if you really understand what it is that you’re doing is my opinion.