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

То, что я пытаюсь понять, состоит в том, чтобы не допустить, чтобы активность загружалась дважды, если я дважды нажимаю кнопку.

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

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

Теперь, поскольку загружаемая активность имеет какое-то отношение к веб-сервису и другим операциям, для загрузки требуется немного времени. Конечно, у меня есть представление для загрузки. Но до этого, если я дважды нажимаю кнопку, я вижу, что активность загружается дважды.

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

Solutions Collecting From Web of "Как предотвратить активность при загрузке дважды при нажатии кнопки"

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

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

Добавьте это в свое определение Activity в Androidmanifest.xml

 android:launchMode = "singleInstance" 

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

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

Это приведет к тому, что только одно действие может быть открыто в верхней части стека истории;

Предположим, что @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?

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

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

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

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

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

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

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

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

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

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

Другое очень простое решение, если вы не хотите использовать 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... } }); 

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

Public boolean oneTimeLoadActivity = false;

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

Если вы используете 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; } } 

Также работает кнопка «Назад», потому что код запроса возвращается на событие.

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

Вы можете просто переопределить 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); } }