Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: click event after Activity.onPause()

There are two buttons, button A starts another activity inside its onClickListener using simple Activity.startActivity() method, button B does some other work inside its onClickListener.

When I click button B and immediately after button A, then new activity is started, onPause() lifecycle event for old activity is fired, but also onClick event for second button is fired, but after Activity.onPause() which leads to some state inconsistencies in my app.

Is there any way to prevent touch/click events from being delivered after onPause() without using isPaused flag?

**Edit:**My code:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button buttonA = (Button) findViewById(R.id.activity_button);
        buttonA.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this, TestActivity.class));
            }
        });

        Button buttonB = (Button) findViewById(R.id.log_button);
        buttonB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e("TEST", "onClick");
            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e("TEST", "onPause");
    }
}

Basically if you are fast enough and click button B right after button A then B's onClick is fired after onPause.

like image 975
Mariusz Avatar asked Jul 14 '16 07:07

Mariusz


People also ask

What is the use of onPause () method?

onPause(): This method gets called when the UI is partially visible to the user. If a dialog is opened on the activity then the activity goes to pause state and calls onPause() method. Here the activity is in the paused state. onStop(): This method gets called when the UI is not visible to the user.

When onDestroy () is called before onPause () and onStop () in an Android application?

Answer: onPause() and onStop() will not be invoked if finish() is called from within the onCreate() method. This might occur, for example, if you detect an error during onCreate() and call finish() as a result. In such a case, though, any cleanup you expected to be done in onPause() and onStop() will not be executed.

When onPause method is called in Android?

onPause. Called when the Activity is still partially visible, but the user is probably navigating away from your Activity entirely (in which case onStop will be called next). For example, when the user taps the Home button, the system calls onPause and onStop in quick succession on your Activity .

What is the difference between onPause () onStop () and onDestroy () lifecycle methods?

Difference between onPause(), onStop() and onDestroy() So, onPause() is logically before onStop(). From onPause() it is possible to call onResume() but it is not possible once onStop() is called. Once onStop() is called then onRestart() can be called. onDestroy() is last in the order after onStop().


3 Answers

In OnClickListener of button A, disable the button b.

Button.setEnabled(false);

Just enable the button at the of A's onClickListener or at onResume depending on your requirements.

like image 80
Riyaz Ahamed Avatar answered Oct 04 '22 14:10

Riyaz Ahamed


I know this question is very old and far far away from being active. I came across this question via a blog.

A simple solution which I can think off is maintaining a flag globally in Activity A and setting it immediately inside onClick of Button A. This flag can be reset in onResume of Activity A.

This flag should be used at the top of onClick handler and all the clicks of all the views must be ignored. Of course, this requires that there is a single onClick method.

private boolean isOnClickIgnored= false;

@Override
public void onResume() {
    super.onResume();
    isOnClickIgnored = false;
}

@Override
public void onClick(View v) {
    super.onClick(v);
    if(isOnClickIgnored){
        return;
    }
    switch (v.getId()){
        case R.id.btnA:
            isOnClickIgnored = true;
            // Do button a things like opening Activity B
            break;
        case R.id.btnB:
            // Do button b things
            break;
        case R.id.btnZ:
            // Do button z things
            break;
    }
}
like image 20
binaryKarmic Avatar answered Oct 04 '22 13:10

binaryKarmic


This whole concept can be easily solved using ViewModels + lifecycle-aware LiveDatas where LiveData expose events to UI-layer only when it's allowed.

like image 23
Mariusz Avatar answered Oct 04 '22 15:10

Mariusz