How to prevent download activity twice when a button is clicked

I am trying to prevent the activity from loading twice if I double-click the button immediately after the first click.

I have an activity that loads at the click of a button, say

myButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { //Load another activity } }); 

Now, since the loaded action has network calls, loading takes a little time (MVC). I show the loading view for this, but if I double-click the button before this, I see that the action is loading twice.

Does anyone know how to prevent this?

+78
android android-activity button onclick
Nov 10 2018-11-11T00:
source share
20 answers

In the button event listener, disable the button and show another activity.

  Button b = (Button) view; b.setEnabled(false); Intent i = new Intent(this, AnotherActitivty.class); startActivity(i); 

Replace onResume() to enable the button again.

 @Override protected void onResume() { super.onResume(); Button button1 = (Button) findViewById(R.id.button1); button1.setEnabled(true); } 
+52
Nov 10 '11 at 10:40
source share

Add this to your Activity definition in AndroidManifest.xml ...

 android:launchMode = "singleTop" 
+136
Nov 10 2018-11-11T00:
source share

You can use intent flags like this.

 Intent intent = new Intent(Class.class); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); activity.startActivity(intent); 

Only one action will be opened at the top of the story stack.

+34
Feb 20 '14 at 11:47
source share

Since SO does not allow me to comment on other answers, I have to pollute this stream with a new answer.

General answers to the "activity opens twice" problem and my experience with these solutions (Android 7.1.1):

  • The shutdown button that launches the action: Works, but feels a little awkward. If you have several ways to get started in your application (for example, the button on the action bar AND, by clicking an item in the list view), you should track the on / off status of several GUI elements. In addition, it is not very convenient to disable the pressed items in a list, for example. Therefore, this is not a very universal approach.
  • launchMode = "singleInstance": does not work with startActivityForResult (), disables navigation using startActivity (), is not recommended for regular applications in the Android manifest documentation.
  • launchMode = "singleTask": does not work with startActivityForResult (), is not recommended for regular applications in the Android manifest documentation.
  • FLAG_ACTIVITY_REORDER_TO_FRONT: Disable button.
  • FLAG_ACTIVITY_SINGLE_TOP: not working, activity still opens twice.
  • FLAG_ACTIVITY_CLEAR_TOP: This is the only one working for me.

EDIT: This was to get started with startActivity (). When using startActivityForResult (), I need to set FLAG_ACTIVITY_SINGLE_TOP and FLAG_ACTIVITY_CLEAR_TOP.

+18
Jun 08 '17 at 10:37
source share

Let's say @wannik is right, but if we have more than one button that invokes the same action listener, and I press two buttons once almost at the same time before starting the next operation ...

So, well, if you have a private boolean mIsClicked = false; field private boolean mIsClicked = false; and in the listener:

 if(!mIsClicked) { mIsClicked = true; Intent i = new Intent(this, AnotherActitivty.class); startActivity(i); } 

And onResume() we need to return the state:

 @Override protected void onResume() { super.onResume(); mIsClicked = false; } 

What is the difference between mine and @wannik?

If you set enabled to false in the listener, calling another button using the same listener will still be enabled. Therefore, to make sure that the listener action is not called twice, you need to have something global that disconnects all listener calls (it doesn’t matter if it is a new instance or not)

What is the difference between my answer and others?

They think correctly, but they do not think about a future return to the same instance of defiant activity :)

+5
Jun 24 '13 at 7:43
source share

Use singleInstance to avoid activating activity twice.

 <activity android:name=".MainActivity" android:label="@string/activity" android:launchMode = "singleInstance" /> 
+5
Jun 03 '16 at 13:44
source share

This only worked for me when startActivity(intent)

 intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); 
+5
Oct 25 '17 at 6:49
source share

I think you are going to solve the problem incorrectly. Generally, a bad idea for an activity is to create lengthy web requests in any of its launch lifecycle methods ( onCreate() , onResume() , etc.). In fact, these methods should simply be used to create and initialize the objects that your activity will use, and therefore should be relatively fast.

If you need to execute a web request, do it in the background thread from a recently launched action (and show the download dialog in the new action). Once the background request thread completes, it can update the action and hide the dialog.

This means that your new activity should start immediately and prevent a double click.

+3
Nov 10 2018-11-11T00:
source share

Hope this helps:

  protected static final int DELAY_TIME = 100; // to prevent double click issue, disable button after click and enable it after 100ms protected Handler mClickHandler = new Handler() { public void handleMessage(Message msg) { findViewById(msg.what).setClickable(true); super.handleMessage(msg); } }; @Override public void onClick(View v) { int id = v.getId(); v.setClickable(false); mClickHandler.sendEmptyMessageDelayed(id, DELAY_TIME); // startActivity() }` 
+3
May 23 '12 at 7:38 a.m.
source share

Another very simple solution, if you do not want to use onActivityResult() , onActivityResult() off the button for 2 seconds (or the time you want), is not ideal, but can partially solve the problem - these are some cases, and the code is simple:

  final Button btn = ... btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { //start activity here... btn.setEnabled(false); //disable button //post a message to run in UI Thread after a delay in milliseconds btn.postDelayed(new Runnable() { public void run() { btn.setEnabled(true); //enable button again } },1000); //1 second in this case... } }); 
+2
Jun 18 '16 at 18:54
source share

In this situation, I will move on to one of two approaches, singleTask in manifest.xml OR in the Activity onResume() and onDestroy() methods, respectively.

For solution first : I prefer to use singleTask for activity in the manifest, rather than singleInstance , using singleInstance . I found out that in some cases creating activity is a new separate instance for myself, the result of which is the presence of two separate application windows in running applications in bcakground and in addition to additional memory allocations, which can lead to a very bad user experience when the user opens the application view, Choose an application to renew. Thus, the best way is for the specific activity in the manifest.xml file to be as follows:

 <activity android:name=".MainActivity" android:launchMode="singleTask"</activity> 

You can check activity trigger modes here .




To solve second, you just need to define a static variable or a preference variable, for example:

 public class MainActivity extends Activity{ public static boolean isRunning = false; @Override public void onResume() { super.onResume(); // now the activity is running isRunning = true; } @Override public void onDestroy() { super.onDestroy(); // now the activity will be available again isRunning = false; } } 

and on the other hand, when you want to start this operation, just check:

 private void launchMainActivity(){ if(MainActivity.isRunning) return; Intent intent = new Intent(ThisActivity.this, MainActivity.class); startActivity(intent); } 
+2
Apr 09 '17 at 11:38 on
source share

Just maintain one flag in the onClick method as:

public boolean oneTimeLoadActivity = false;

  myButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if(!oneTimeLoadActivity){ //start your new activity. oneTimeLoadActivity = true; } } }); 
0
Nov 10 '11 at 10:05
source share

If you use onActivityResult, you can use a variable to save state.

 private Boolean activityOpenInProgress = false; myButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if( activityOpenInProgress ) return; activityOpenInProgress = true; //Load another activity with startActivityForResult with required request code } }); protected void onActivityResult(int requestCode, int resultCode, Intent data) { if( requestCode == thatYouSentToOpenActivity ){ activityOpenInProgress = false; } } 

The back button is pressed, as the request code returns to the event.

0
Oct 30 '15 at 10:01
source share

Addendum:

 android:launchMode="singleTop" 

Inside the activity tag in AndroidManifest.xml, the problem is resolved.

0
Oct 08 '18 at 12:42
source share

a more general solution, which will be applied only once for all applications, is to add the following two classes, as shown below

 public class SingleClickButton extends AppCompatButton { public SingleClickButton(Context context) { super(context); } public SingleClickButton(Context context, AttributeSet attrs) { super(context, attrs); } public SingleClickButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public void setOnClickListener(@Nullable OnClickListener l) { if(l!=null){ super.setOnClickListener(new DebouncedClickListener() { @Override public void onClicked(View v) { l.onClick(v); } }); }else{ super.setOnClickListener(l); } } } public abstract class DebouncedClickListener implements View.OnClickListener { private static final long MAX_TIME_INTERVAL = 750L; private long lastClickedTime; public abstract void onClicked(View v); @Override public void onClick(View v) { Logger.d("Click Test trying to click"); long now = SystemClock.elapsedRealtime(); long diff = now - lastClickedTime; if (diff > MAX_TIME_INTERVAL) { Logger.d("Click Test allowed to click"); onClicked(v); }else{ Logger.d("Click Test not allowed to click time "); } lastClickedTime = now; } } 

so whenever you want a button with one click, just add a custom view to the XML as shown below

 <yourpackagge.SingleClickButton .... /> 
0
Jan 26 '19 at 11:11
source share
 myButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { myButton.setOnClickListener(null); } }); 
-one
Nov 10 2018-11-11T00:
source share

Use the flag variable, set it to true . Check if its true return actually performs an Activity Call.

You can also use setClickable (false) making an Activity call

 flg=false public void onClick(View view) { if(flg==true) return; else { flg=true; // perform click} } 
-one
Nov 10 2018-11-11T00:
source share

You can simply override startActivityForResult and use the instance variable:

 boolean couldStartActivity = false; @Override protected void onResume() { super.onResume(); couldStartActivity = true; } @Override public void startActivityForResult(Intent intent, int requestCode, Bundle options) { if (couldStartActivity) { couldStartActivity = false; intent.putExtra(RequestCodeKey, requestCode); super.startActivityForResult(intent, requestCode, options); } } 
-one
Jul 17 '15 at 17:42
source share

// variable to track the time of the event

 private long mLastClickTime = 0; 

2. In onClick, check that if the current time and the time difference of the last click is less than I second, then do not take any action (return), otherwise go to the click event.

  @Override public void onClick(View v) { // Preventing multiple clicks, using threshold of 1 second if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) { return; } mLastClickTime = SystemClock.elapsedRealtime(); // Handle button clicks if (v == R.id.imageView2) { // Do ur stuff. } else if (v == R.id.imageView2) { // Do ur stuff. } } } 
-2
Mar 20 '19 at 8:14
source share

You can also try this.

 Button game = (Button) findViewById(R.id.games); game.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent myIntent = new Intent(view.getContext(), Games.class); startActivityForResult(myIntent, 0); } }); 
-four
Nov 10 2018-11-11T00:
source share



All Articles