3

In order to show a last state in a BottomSheetDialogFragment I try to implement as below,

*) Activity:

    private var languageSelectorBsFragment: LanguageSelectorBsFragment? = null


    @OnClick(R.id.txt_imc_clip_language)
    fun onClickClipLanguage() {
        initLanguageBottomSheet()
        languageSelectorBsFragment?.show(supportFragmentManager, languageSelectorBsFragment!!.tag)
    }

    private fun initLanguageBottomSheet() {
        if (languageSelectorBsFragment == null) {
           languageSelectorBsFragment = LanguageSelectorBsFragment.newInstance(LanguageSelectorBsFragment.TYPE_USER)
        }
    }

*) BottomSheetDialogFragment

class LanguageSelectorBsFragment : BottomSheetDialogFragment() {
   var lastSelectedLanguageId: String?;
   var userInputInEditText: String?;
}

So that there is only one instance of BottomSheetDialogFragment and I need to keep a reference of many othervariables that the user has interacted with when the bottom sheet last time opened.

By doing the above steps I am able to achieve our requirement but several times it is randomly crashing and I am unable to find the root cause.

*) Exception:

Fatal Exception: java.lang.IllegalStateException: Fragment already added: LanguageSelectorBsFragment{2b446ae} (8fe75d96-932d-47eb-97af-128319431a55)}
       at androidx.fragment.app.FragmentStore.addFragment(FragmentStore.java:67)
       at androidx.fragment.app.FragmentManager.addFragment(FragmentManager.java:1563)
       at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:405)
       at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2167)
       at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1990)
       at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1945)
       at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1847)
       at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
       at android.os.Handler.handleCallback(Handler.java:751)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:154)
       at android.app.ActivityThread.main(ActivityThread.java:6351)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:896)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:786)

I know there are already many existing questions with an exact similar exception and the closest which I can think of is this.

Also, I have to use BottomSheetDialogFragment and can not use "Persistent Bottom Sheet". I seriously hope that Android should provide show and hide feature for "Modal Bottom Sheet" and not dismiss every time it closes.

*) Questions:

1) How to prevent this crash?

2) Is there a way to "hide" Modal Bottom Sheet without "dismiss"?

Chitrang
  • 5,097
  • 1
  • 35
  • 58
  • "Also, I have to use BottomSheetDialogFragment and can not use "Persistent Bottom Sheet"." - this is exactly wrong if you're looking for "hide" without "dismiss", that's why they are two separate things for two separate use cases – ianhanniballake Sep 30 '20 at 01:29
  • Thanks for the prompt response. There are many use cases I can think of, for example, "filter" selection bottom sheet which can be used throughout the app. Hence, I want to make it independent and not bind with just one activity. However, there should be some way to show the last selections options if the user is opening the same bottom sheet multiple times at the very same activity. – Chitrang Sep 30 '20 at 01:44
  • I have also observed that somehow BottomSheetDialogFragment is doing this. Because if I keep reference of BottomSheetDialogFragment and just show() it then  it shows what user has entered in edittext lasttime and also an exact scroll position of item in recyclerview if we pass same data. But I am not sure how? – Chitrang Sep 30 '20 at 01:45

1 Answers1

0

I had this problem myself and this is a way I handled it, maybe it will help you.
I had to keep state of the BottomSheetDialogFragment throughout the lifecycle of the Fragment that this dialog was showing on top of.

So basically, I created a shared ViewModel that there is one instance of it for the fragment and the same instance for each dialog that is shown.
This way, you can have same data every time you show the dialog.
Simple implementation is shown here.

This way, you don't need to hold an instance to a dialog in your activity and just access the data in the dialog via the ViewModel. It's really clean and easy to maintain.

baltekg
  • 985
  • 9
  • 31