Подтвердить что ты не робот

Как предотвратить активность при загрузке дважды при нажатии кнопки

Я пытаюсь предотвратить загрузку активности дважды, если дважды нажать кнопку сразу после первого щелчка.

У меня есть активность, которая загружается по нажатию кнопки, скажем

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

Теперь, поскольку загружаемое действие имеет сетевые вызовы, загрузка занимает немного времени (MVC). Я показываю вид загрузки для этого, но если я дважды нажму кнопку до этого, я вижу, что действие загружается дважды.

Кто-нибудь знает, как это предотвратить?

4b9b3361

Ответ 1

В прослушивателе событий кнопки отключите кнопку и покажите другую активность.

    Button b = (Button) view;
    b.setEnabled(false);

    Intent i = new Intent(this, AnotherActitivty.class);
    startActivity(i);

Заменить onResume(), чтобы снова включить кнопку.

@Override
    protected void onResume() {
        super.onResume();

        Button button1 = (Button) findViewById(R.id.button1);
        button1.setEnabled(true);
    }

Ответ 2

Добавьте это к определению Activity в AndroidManifest.xml...

android:launchMode = "singleTop"

Например:

<activity
            android:name=".MainActivity"
            android:theme="@style/AppTheme.NoActionBar"
            android:launchMode = "singleTop"/>

Ответ 3

Вы можете использовать флаги намерения как это.

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

В верхней части стека истории будет открыто только одно действие.

Ответ 4

Так как SO не позволяет мне комментировать другие ответы, я должен загрязнить этот поток новым ответом.

Общие ответы на проблему "активность открывается дважды" и мой опыт с этими решениями (Android 7.1.1):

  • Кнопка отключения, которая запускает действие: Работает, но чувствует себя немного неуклюжей. Если у вас есть несколько способов начать работу в вашем приложении (например, кнопку на панели действий И, щелкнув элемент в представлении списка), вы должны отслеживать состояние включения/отключения нескольких элементов GUI. Кроме того, не очень удобно отключать нажатые элементы в виде списка, например. Таким образом, это не очень универсальный подход.
  • launchMode = "singleInstance": не работает с startActivityForResult(), отключает навигацию с помощью startActivity(), не рекомендуется для обычных приложений в документации к манифесту Android.
  • launchMode = "singleTask": не работает с startActivityForResult(), не рекомендуется для обычных приложений в документации к манифесту Android.
  • FLAG_ACTIVITY_REORDER_TO_FRONT: кнопка "Отключает".
  • FLAG_ACTIVITY_SINGLE_TOP: не работает, активность все еще открывается дважды.
  • FLAG_ACTIVITY_CLEAR_TOP: Это единственная работающая для меня.

EDIT: Это было для начала работы с startActivity(). При использовании startActivityForResult() мне нужно установить FLAG_ACTIVITY_SINGLE_TOP и FLAG_ACTIVITY_CLEAR_TOP.

Ответ 5

Скажем, @wannik прав, но если у нас есть более одной кнопки, вызывающей один и тот же прослушиватель действий, и я нажимаю две кнопки один раз почти одновременно, прежде чем начать следующую операцию...

Итак, хорошо, если у вас есть поле private boolean mIsClicked = false; и в слушателе:

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

И onResume() нам нужно вернуть состояние:

@Override
protected void onResume() {
    super.onResume();

    mIsClicked = false;
}

Какая разница между моим и @wannik?

Если вы установили enabled в false в прослушивателе, вызывающий вызов другой кнопки, используя тот же прослушиватель, все равно будет включен. Поэтому, чтобы убедиться, что действие прослушивателя не вызывается дважды, вам нужно иметь что-то глобальное, которое отключает все вызовы слушателя (неважно, если это новый экземпляр или нет)

В чем разница между моим ответом и другими?

Они думают правильно, но они не думают о будущем возвращении к тому же экземпляру вызывающей активности:)

Ответ 6

Используйте singleInstance, чтобы избежать активизации активности дважды.

<activity
            android:name=".MainActivity"
            android:label="@string/activity"
            android:launchMode = "singleInstance" />

Ответ 7

Это работало только для меня, когда startActivity(intent)

intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

Ответ 8

Я думаю, вы собираетесь решить проблему неправильно. Как правило, плохой идеей для деятельности является создание длительных веб-запросов в любом из его методов жизненного цикла запуска (onCreate(), onResume() и т.д.). На самом деле эти методы должны просто использоваться для создания и инициализации объектов, которые ваша деятельность будет использовать, и поэтому должны быть относительно быстрыми.

Если вам нужно выполнить веб-запрос, сделайте это в фоновом потоке из недавно запущенного действия (и покажите диалог загрузки в новом действии). Как только поток фонового запроса завершается, он может обновить действие и скрыть диалог.

Это означает, что ваша новая активность должна немедленно запускаться и предотвратить двойной щелчок.

Ответ 9

Надеюсь, что это поможет:

 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()
}`

Ответ 10

Другое очень простое решение, если вы не хотите использовать onActivityResult(), отключает кнопку в течение 2 секунд (или время, которое вы хотите), не является идеальным, но может частично решить проблему - это некоторые случаи, и код прост:

   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...
        }
    });

Ответ 11

В этой ситуации я перейду к одному из двух подходов, singleTask в manifest.xml ИЛИ в методах Activity onResume() и onDestroy() соответственно.

Для решения first: я предпочитаю использовать singleTask для активности в манифесте, а не singleInstance, используя singleInstance. Я выяснил, что в некоторых случаях создание активности новый отдельный экземпляр для себя, результатом которого является наличие двух отдельных окон приложений в запущенных приложениях в bcakground и помимо дополнительных распределений памяти, которые могут привести к очень плохому пользовательскому опыту, когда пользователь откроет представление приложений, чтобы выбрать какое-либо приложение для возобновления. Таким образом, лучший способ состоит в том, чтобы определенная активность в файле manifest.xml была следующей:

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

вы можете проверить режимы запуска активности здесь.


Для решения second вам нужно просто определить статическую переменную или переменную предпочтения, например:

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;
    }

}

а с другой стороны, когда вы хотите запустить эту операцию, просто проверьте:

private void launchMainActivity(){
    if(MainActivity.isRunning)
        return;
    Intent intent = new Intent(ThisActivity.this, MainActivity.class);
    startActivity(intent);
}

Ответ 12

Просто поддерживайте один флаг в методе onClick в качестве:

public boolean oneTimeLoadActivity = false;

    myButton.setOnClickListener(new View.OnClickListener() {
          public void onClick(View view) {
               if(!oneTimeLoadActivity){
                    //start your new activity.
                   oneTimeLoadActivity = true;
                    }
        }
    });

Ответ 13

Если вы используете onActivityResult, вы можете использовать переменную для сохранения состояния.

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;
  }
}

Нажимается кнопка "Назад", так как код запроса возвращается на событие.

Ответ 14

Добавление:

android:launchMode="singleTop"

Внутри тега активности в AndroidManifest.xml проблема решена.

Ответ 15

более общее решение, которое будет применено только один раз для всех приложений, состоит в добавлении следующих двух классов, как показано ниже

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;
    }

}

поэтому всякий раз, когда вы хотите кнопку одним щелчком мыши, просто добавьте пользовательский вид в XML, как показано ниже

<yourpackagge.SingleClickButton .... />

Ответ 16

myButton.setOnClickListener(new View.OnClickListener() {
      public void onClick(View view) {
      myButton.setOnClickListener(null);
    }
});

Ответ 17

Используйте переменную flag, установите ее to true, Проверьте, действительно ли его true return выполняет Activity Call.

Вы также можете использовать setClickable (false), выполняющий вызов Activity

flg=false
 public void onClick(View view) { 
       if(flg==true)
         return;
       else
       { flg=true;
        // perform click}
    } 

Ответ 18

Вы можете просто переопределить startActivityForResult и использовать переменную экземпляра:

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);
    }
}

Ответ 19

//переменная для отслеживания времени события

private long mLastClickTime = 0;

2. В onClick проверьте, что если текущее время и разница во времени последнего клика меньше, чем я секунда, то не предпринимайте никаких действий (возврат), иначе перейдите к событию клика.

 @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.
         }
      }
 }

Ответ 20

Вы также можете попробовать это.

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);
            }

        });