Day
Day

Reputation: 904

Snackbar sometimes doesn't show up when it replaces another one

I encountered a weird issue with Snackbars on android. I show error messages via an Snackbar + Retry-Action. When 'Retry' is clicked and the error is still here (e.g. no internet) I show the error again. This click on the action in the Snackbar automatically dismisses the currently shown one, and showing a new Snackbar while the old one still 'fades out' works as expected.

But sometimes (when I click 'Retry' ~30 times) a Snackbar doesn't show up at all after I press the button many times.

I can reproduce it with this simple code:

final View.OnClickListener retryListener = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        showSnackbar();
    }
};

private void showSnackbar() {
    Snackbar snackbar = Snackbar.make(root, "Error", BaseTransientBottomBar.LENGTH_INDEFINITE)
            .setAction("Retry", retryListener)
            //Callback only for debugging-purposes
            .addCallback(new BaseTransientBottomBar.BaseCallback<Snackbar>() {
                @Override
                public void onShown(Snackbar transientBottomBar) {
                    super.onShown(transientBottomBar);
                    Log.d(TAG, "onShown called");
                }
            });
    snackbar.show();
    Log.d(TAG, "show called");
}

When I take a look at logcat after the problem occurs with this code, the last line is show called and the onShown-callback wasn't called anymore.

Why would this happen? Should I report this as an issue? Any workarounds known?

Upvotes: 6

Views: 2506

Answers (2)

Gnzlt
Gnzlt

Reputation: 4572

Apparently, if you dismiss the current SnackBar and wait a little to show it again, it works. I'm using a Kotlin Extension Function to make it simpler to use:

fun Snackbar.dismissAndShow() {
    if (isShownOrQueued) {
        dismiss()
        view.postDelayed(1000L) { show() }
    } else {
        show()
    }
}

So then I call it like:

mySnackBar.dismissAndShow()

Upvotes: 0

Day
Day

Reputation: 904

I haven't found a real reason why it happens nor a real solution to the problem, but I found a workaround which works for me:

private Snackbar currentlyShownSnackbar;    

private void showSnackbar() {
    Snackbar snackbar = Snackbar.make(...);
    snackbar.show();
    currentlyShownSnackbar = snackbar;
}

Simply by keeping a reference to the currently shown Snackbar, this problem doesn't happen anymore. I don't know why, maybe it is related to too early garbage-collection.

Code inspection will say that this variable is assigned but never used - this warning can be ignored.

I also added this in my Activity to prevent any possible memory leak:

public void onPause() {
    super.onPause();
    this.currentlyShownSnackbar = null;
}

Upvotes: 8

Related Questions