Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Cómo evitar que la actividad se cargue dos veces al presionar el botón

Lo que estoy tratando de averiguar es evitar que la actividad se cargue dos veces si presiono el botón dos veces.

Tengo una actividad que carga en el tecleo de un botón, diga

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

Ahora, porque la actividad a cargar tiene algo que ver con el servicio web y otras operaciones, se necesita un poco de tiempo para que se cargue. Por supuesto, tengo una vista de carga para esto. Pero antes de eso, si presiono el botón dos veces, puedo ver la actividad cargada dos veces.

¿Alguien sabe cómo prevenir esto?

  • OnItemClickListener usando ArrayAdapter para ListView
  • Listview no se puede hacer clic cuando se puede seleccionar la vista de texto dentro de esa vista de lista
  • Android: Evento de clic de botón
  • Evitar que DialogFragment se rechace cuando se hace clic en el botón
  • Método onClick de Android
  • Adaptador personalizado para gridview en android
  • ButterKnife onclick no funciona
  • OnClick posición en cadena en TextView
  • 16 Solutions collect form web for “Cómo evitar que la actividad se cargue dos veces al presionar el botón”

    En el detector de eventos del botón, deshabilite el botón y muestre otra actividad.

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

    onResume() para volver a activar el botón.

     @Override protected void onResume() { super.onResume(); Button button1 = (Button) findViewById(R.id.button1); button1.setEnabled(true); } 

    Agrega esto a la definición de tu Activity en Androidmanifest.xml

     android:launchMode = "singleInstance" 

    Puede utilizar los indicadores de intención como este.

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

    Se hará que sólo una actividad puede estar abierta en la parte superior de la pila de historia,

    Digamos que @wannik tiene razón, pero si tenemos más de 1 botón llamando al mismo oyente de acción y presiono dos botones una vez casi al mismo tiempo antes de iniciar la siguiente actividad …

    Por lo tanto, es bueno si tiene campo private boolean mIsClicked = false; Y en el oyente:

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

    Y onResume() necesitamos devolver el estado:

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

    ¿Cuál es la deferencia entre la respuesta de mi y @ wannik?

    Si establece activado a false en el oyente de su vista de llamada, otro botón que utiliza el mismo oyente seguirá estando habilitado. Así que para estar seguro de que la acción del oyente no se llama dos veces que necesita tener algo global que deshabilita todas las llamadas del oyente (nunca importa si es nueva instancia o no)

    ¿Cuál es la diferencia entre mi respuesta y otras?

    Están pensando de la manera correcta pero no están pensando para el futuro vuelven a la misma instancia de la actividad que llama 🙂

    Espero que esto ayude:

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

    Creo que vas a resolver el problema de la manera equivocada. En general, es una mala idea que una actividad esté realizando solicitudes web de larga duración en cualquiera de sus métodos de ciclo de vida de inicio ( onCreate() , onResume() , etc.)). Realmente estos métodos deben ser utilizados simplemente para instanciar e inicializar objetos que su actividad utilizará y por lo tanto deben ser relativamente rápidos.

    Si necesita realizar una solicitud web, haga esto en un subproceso de fondo de su actividad recién iniciada (y muestre el diálogo de carga en la nueva actividad). Una vez completado el subproceso de solicitud de fondo, puede actualizar la actividad y ocultar el diálogo.

    Esto significa que su nueva actividad debe ser lanzada inmediatamente y evitar que el doble clic sea posible.

    Use singleInstance para evitar la actividad de invocar dos veces.

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

    Otra solución muy muy simple si no quieres usar onActivityResult() es desactivar el botón durante 2 segundos (o tiempo que quieras), no es ideal, pero puede solucionar en parte el problema es algunos casos y el código es 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... } }); 

    Basta con mantener una bandera en el botón onClick método como:

    Public boolean oneTimeLoadActivity = false;

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

    Si está usando onActivityResult, podría usar una variable para guardar el estado.

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

    Funciona en el botón Atrás presionado también porque el código de solicitud se devuelve en el evento.

    Para esta situación, voy a ir para uno de los dos abordados, singleTask en manifest.xml O un indicador en los onResume() y onDestroy() , respectivamente.

    Para la primera solución: Prefiero usar singleTask para la actividad en el manifiesto en lugar de singleInstance , como por singleInstance he descubierto que en algunas ocasiones la actividad de crear una nueva instancia separada por sí mismo que resultan tener una ventana de dos aplicaciones independientes en Las aplicaciones en ejecución en bcakground y además de asignaciones de memoria adicionales que resultarían en una experiencia de usuario muy mala cuando el usuario abra la vista de aplicaciones para elegir alguna aplicación para reanudar. Así pues, la mejor manera es tener la actividad definida en el manifest.xml como el siguiente:

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

    Puede comprobar los modos de lanzamiento de la actividad aquí .


    Para la segunda solución, sólo tiene que definir una variable estática o una variable de preferencia, por ejemplo:

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

    Y desde el otro lado cuando desee iniciar esta actividad, solo marque:

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

    Como SO no me permite comentar sobre otras respuestas, tengo que contaminar este hilo con una nueva respuesta.

    Respuestas comunes para el problema de la "actividad se abre dos veces" y mis experiencias con estas soluciones (Android 7.1.1):

    1. Deshabilitar botón que inicia la actividad: Funciona, pero se siente un poco torpe. Si tiene varias maneras de iniciar la actividad en su aplicación (por ejemplo, un botón en la barra de acción Y haciendo clic en un elemento en una vista de lista), debe realizar un seguimiento del estado activado / desactivado de varios elementos GUI. Además, no es muy conveniente desactivar los elementos que se han hecho clic en una vista de lista, por ejemplo. Por lo tanto, no es un enfoque muy universal.
    2. LaunchMode = "singleInstance": No funciona con startActivityForResult (), rompe la navegación con startActivity (), no recomendado para aplicaciones regulares por la documentación del manifiesto de Android.
    3. LaunchMode = "singleTask": No funciona con startActivityForResult (), no recomendado para aplicaciones regulares por la documentación del manifiesto de Android.
    4. FLAG_ACTIVITY_REORDER_TO_FRONT: Borrado del botón.
    5. FLAG_ACTIVITY_SINGLE_TOP: No funciona, la actividad se abre todavía dos veces.
    6. FLAG_ACTIVITY_CLEAR_TOP: Este es el único que funciona para mí.

    EDIT: Esto fue para iniciar las actividades con startActivity (). Cuando utilizo startActivityForResult () necesito establecer FLAG_ACTIVITY_SINGLE_TOP y FLAG_ACTIVITY_CLEAR_TOP.

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

    Utilice una variable de flag establecida to true , Compruebe si su verdadero sólo return otra actividad.

    También puede utilizar setClickable (false) ejecutando la Actividad

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

    Puedes probar esto también

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

    Sólo podría anular startActivityForResult y utilizar la variable de instancia:

     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); } } 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.