stripe-react-native icon indicating copy to clipboard operation
stripe-react-native copied to clipboard

Fragments shouldn't have variables in default constructor

Open remonh87 opened this issue 2 years ago • 2 comments

Describe the bug In both GooglePayFragment and PaymentSheetFragment we create a fragment and inject variables in the constructor. This is considered a bad practice and can lead to undesired side effects. Reason for having an 0 arg constructor is that Android can recreate the fragment itself when config changes.

See this link for a good explanation of the issue

To Reproduce We got issues in our library that the app crashes randomly when users put the app in the background. See: https://github.com/flutter-stripe/flutter_stripe/issues/996.

Reproduction is hard some could reproduce it like:

  1. Enable "Don't keep activities" in Developer Options.
  2. After calling Stripe.instance.initPaymentSheet(...) somewhere, put the app in background.
  3. Re-enter the app. Result: The app crashes after splash with the following stacktrace:
E/AndroidRuntime( 1575): java.lang.RuntimeException: Unable to start activity ...
androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment com.reactnativestripesdk.PaymentSheetFragment: could not find Fragment constructor
E/AndroidRuntime( 1575): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4166)
E/AndroidRuntime( 1575): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4312)
E/AndroidRuntime( 1575): 	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
E/AndroidRuntime( 1575): 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
E/AndroidRuntime( 1575): 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
E/AndroidRuntime( 1575): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2571)
E/AndroidRuntime( 1575): 	at android.os.Handler.dispatchMessage(Handler.java:106)
E/AndroidRuntime( 1575): 	at android.os.Looper.loopOnce(Looper.java:226)
E/AndroidRuntime( 1575): 	at android.os.Looper.loop(Looper.java:313)
E/AndroidRuntime( 1575): 	at android.app.ActivityThread.main(ActivityThread.java:8741)
E/AndroidRuntime( 1575): 	at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 1575): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
E/AndroidRuntime( 1575): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
E/AndroidRuntime( 1575): Caused by: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment com.reactnativestripesdk.PaymentSheetFragment: could not find Fragment constructor
E/AndroidRuntime( 1575): 	at androidx.fragment.app.Fragment.instantiate(Fragment.java:678)
E/AndroidRuntime( 1575): 	at androidx.fragment.app.FragmentContainer.instantiate(FragmentContainer.java:57)
E/AndroidRuntime( 1575): 	at androidx.fragment.app.FragmentManager$3.instantiate(FragmentManager.java:507)
E/AndroidRuntime( 1575): 	at androidx.fragment.app.FragmentState.instantiate(FragmentState.java:81)
E/AndroidRuntime( 1575): 	at androidx.fragment.app.FragmentStateManager.<init>(FragmentStateManager.java:85)
E/AndroidRuntime( 1575): 	at androidx.fragment.app.FragmentManager.restoreSaveStateInternal(FragmentManager.java:2505)
E/AndroidRuntime( 1575): 	at androidx.fragment.app.FragmentManager.attachController(FragmentManager.java:2665)
E/AndroidRuntime( 1575): 	at androidx.fragment.app.FragmentController.attachHost(FragmentController.java:117)
E/AndroidRuntime( 1575): 	at androidx.fragment.app.FragmentActivity.lambda$init$3$androidx-fragment-app-FragmentActivity(FragmentActivity.java:140)
E/AndroidRuntime( 1575): 	at androidx.fragment.app.FragmentActivity$$ExternalSyntheticLambda0.onContextAvailable(Unknown Source:2)
E/AndroidRuntime( 1575): 	at androidx.activity.contextaware.ContextAwareHelper.dispatchOnContextAvailable(ContextAwareHelper.java:99)
E/AndroidRuntime( 1575): 	at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:362)
E/AndroidRuntime( 1575): 	at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:217)
E/AndroidRuntime( 1575): 	at io.flutter.embedding.android.FlutterFragmentActivity.onCreate(FlutterFragmentActivity.java:279)
E/AndroidRuntime( 1575): 	... 15 more
E/AndroidRuntime( 1575): Caused by: java.lang.NoSuchMethodException: com.reactnativestripesdk.PaymentSheetFragment.<init> []
E/AndroidRuntime( 1575): 	at java.lang.Class.getConstructor0(Class.java:2363)
E/AndroidRuntime( 1575): 	at java.lang.Class.getConstructor(Class.java:1759)
E/AndroidRuntime( 1575): 	at androidx.fragment.app.Fragment.instantiate(Fragment.java:663)
E/AndroidRuntime( 1575): 	... 30 more

Expected behavior The fragments should have an empty constructor so Android can recreate it when needed.

Desktop (please complete the following information): Android

remonh87 avatar Jan 15 '23 08:01 remonh87

Getting lots of reports of this crash from our app in prod

marcshilling avatar Oct 23 '23 13:10 marcshilling

Any reason this has not been fixed yet? Curious, as wee see crashes from this in our production app.

joknjokn avatar Aug 14 '24 08:08 joknjokn