6

There are a lot of questions related to back stack management, but none really satisfied me. The closer I found is that one but it looks like an ugly workaround to me.

When clicking on a button in activity A, I'm launching an activity B with startActivityForResult(), expecting a simple A -> B back stack. But if you spam the button fast enough, you end up with two intents being fired and thus two activities stacked A -> B -> B.

I tried to use FLAG_ACTIVITY_SINGLE_TOP flag to prevent the second B activity from being created but it didn't change anything:

This is the button listener in activity A:

btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(getApplicationContext(), ActivityB.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivityForResult(intent, REQUEST_CODE);
    }
});

And logs clearly states that onCreate() in invoked twice (instead of the expected onNewIntent):

btn.onClick()

activityB.onCreate()

btn.onClick()

activityB.onCreate()

My activity must not be singleTask nor singleInstance, they should just be part of the back stack as any regular activity. Any clearance would be much appreciated!

Community
  • 1
  • 1
bagage
  • 1,094
  • 1
  • 21
  • 44
  • Disable the button after it is clicked. If you're really concerned, keep a flag to denote whether you should call `startActivityForResult()` again. – CommonsWare Sep 15 '17 at 14:02
  • can you publish your manifest? (regarding the 2 activities) – MatPag Sep 15 '17 at 15:08
  • @CommonsWare although disabling the button sounds like a good approach, often it isn't effective (especially if the phone is busy, or just a low-end device that has a slow CPU). Because clicking the button can occur multiple times before `onClick()` has been called (at which time the damage is already done and disabling the button is too late). – David Wasser Sep 15 '17 at 17:33

1 Answers1

-1

Your problem is two activity started by you button click spamming.

In a simple way set boolean field to prevent starting two activities.

Example:

boolean isClicked;
button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(!isClicked){
                 isClicked = true;
                 //start activity here.
                }
            }
        });

In your onPause() set the boolean field false.

Bhuvanesh BS
  • 13,474
  • 12
  • 40
  • 66
  • That's the "solution" I linked in the question and that I'd like to avoid. Apart he fact that it adds almost 10 lines of no-value code, it looks like nightmare to maintain, given the fact that you may have dozens of buttons opening activities. – bagage Sep 15 '17 at 14:23
  • Why don't you make a method to start activity. So wherever you call the activity. You can handle the bit field in single place – Bhuvanesh BS Sep 15 '17 at 14:37
  • 1
    This is the only correct approach. When you click a button, it doesn't immediately call the `onClick()` method. All it does it post an event "button clicked" to the internal event queue. Depending on how busy your phone is, how many apps are running, how fast your CPU is and a million other variables (over which you have no control), the button can be clicked multiple times before your `onClick()` method is called. You can do nothing to prevent this. All you can do is make sure that when `onClick()` is actually called, you make sure that you don't process the event more than once. – David Wasser Sep 15 '17 at 17:28
  • 3
    Although it may seem "hacky", it isn't. It isn't unmaintainable, it is "best practice", and you will find that often you need to somehow keep track of the fact that you launched another `Activity` anyway (because you've changed internal state, because you need to remember that you are waiting for `onActivityResult()` to be called, etc.) so that it is a normal part of processing `onClick()` events. – David Wasser Sep 15 '17 at 17:31
  • 1
    Nice information. Thank you so much for sharing such a awesome information. @David Wasser – Bhuvanesh BS Sep 15 '17 at 17:46
  • I never saw such code in apps but they might have not handled that actually. if this is considered best practice I'll follow that approach, even if I don't like it much. Thanks @DavidWasser. – bagage Sep 15 '17 at 19:49
  • @bagage, do you remember if you stayed with that solution? Or did you find something better ever after? – xian Sep 07 '20 at 13:12