Estoy tratando de evitar que la actividad de carga dos veces si me presione dos veces el botón inmediatamente después del primer clic.

Tengo una actividad que se carga en el clic de un botón, dicen

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

Ahora debido a que la actividad se ha cargado llamadas de la red, se necesita un poco de tiempo para cargar (MVC). Yo sí muestran una carga de la vista de esto, pero si yo pulse el botón dos veces antes de eso, puedo ver la actividad que se está cargando dos veces.

Hacer cualquiera sabe cómo para evitar esto?

  • Usted puede deshabilitar el botón después de la apertura de la actividad…y cuando la actividad acabado,vuelve a activar…u puede detectar el final de la segunda actividad llamando onActivityResult función
  • Deshabilitar el botón cuando se hace clic y volver a activarlo más tarde sólo cuando se desea que el botón se hace clic de nuevo.
  • la desactivación no funciona de una manera sencilla, si la siguiente afirmación es un poco largo proceso o de inicio de actividad… Para deshabilitar el botón debe tener para crear un subproceso independiente…
  • Si golpear a la misma API dos veces se refieren a continuación: techstricks.com/avoid-multiple-requests-when-using-volley
  • Posibles duplicados de botón Evitar múltiples rápida clics
InformationsquelleAutor tejas | 2011-11-10

18 Comentarios

  1. 55

    En el botón de escucha de eventos, deshabilitar el botón y mostrar otra actividad.

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

    Reemplazar onResume() para volver a habilitar el botón.

    @Override
        protected void onResume() {
            super.onResume();
    
            Button button1 = (Button) findViewById(R.id.button1);
            button1.setEnabled(true);
        }
    • Este es el enfoque correcto. Incluso el Botón de la manija Estados Seleccionados para usted (si usted provea) y todo el Material de Diseño «golosinas» que usted esperaría de un simple Widget. Yo no puedo creer que la gente utilice temporizadores para esto. Entonces usted empieza a ver la extraña bibliotecas para manejar cosas como estas…
  2. 138

    Agregar esto a su Activity definición en AndroidManifest.xml

    android:launchMode = "singleTop"

    Por ejemplo:

    <activity
                android:name=".MainActivity"
                android:theme="@style/AppTheme.NoActionBar"
                android:launchMode = "singleTop"/>
    • ok supongo que están haciendo algunos de procesamiento después de comenzar la actividad.. es por eso Que la pantalla se convierte en negro. Ahora, si queremos evitar que la pantalla en negro, usted debe mostrar un cuadro de diálogo de progreso en el inicio de la actividad y hacer el tiempo de procesamiento en un hilo separado (es decir, Subproceso de interfaz de usuario o Simplemente el uso de async clase). Una vez que su procesamiento se realiza ocultar ese diálogo. Es la mejor solución en mi conocimiento y lo he utilizado varias veces…:)
    • Tengo el cuadro de diálogo para mostrar. Pero sí, yo tengo un método que apunta web en el onCreate. Pero es que esta es la única solución? Porque en este punto, quiero manejar sin cambiar el hilo y todo. Así que ¿conoces otras formas posibles. Y estoy teniendo el botón en mi lista de adaptador y he declarado el método para que en el xml, no mediante programación
    • ¿qué más es posible??? De una manera u otra debe tener para implementar roscado para obtener una superficie lisa en busca de la aplicación… prueba tio..;) Sólo hay que poner todo el código en un método para llamar a ese método desde un subproceso independiente en el mismo lugar donde has escrito lo anterior… Se olvidará de aumentar de cinco a seis líneas de código..
    • Yo uso un webview con una interfaz javascript, en Jelly bean mi método es despedido dos veces!, esta solución funciona perfecto! gracias Awais
    • Gracias por la solución. Pero cuando startActivity(…), veo una pantalla en negro por un tiempo. Trato de usar singleTask en lugar de instancia única y funciona bien.
    • Esto impide que dos instancias de la actividad de los existentes, pero ello no impide que el código se ejecute dos veces, incorrectamente. El aceptó respuesta es mejor, a pesar de tener menos votos.
    • Esto está mal, esto hace que la actividad nunca existirán dos veces, incluso en las diferentes tareas. La forma correcta sería android:launchMode = "singleTop", que logra el efecto sin romper Android multitarea. La documentación indica que la mayoría de las aplicaciones no deben utilizar el singleInstance opción.
    • Para su INFORMACIÓN: Si se utiliza la actividad de las transiciones de cosas podría romperse si usted confía en esta configuración

  3. 35

    Puede utilizar la intención banderas como este.

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

    Va a hacer sólo una actividad abierta en la parte superior de la historia de la pila.

    • esta debe ser la correcta android-modo de respuesta
    • Esta respuesta, combinada con la más upvoted respuesta parece funcionar mejor. El uso de este indicador en la Actividad de manifiesto: android:launchMode = "singleTop", de esta manera se resuelve sin tener que añadir la bandera a cada Intención.
    • esto no es muy útil cuando usted necesita anidada actividades, porque no se puede tener dos del mismo tipo de actividad.
    • Esto no funciona en el caso de startActivityForResult
  4. 21

    Ya que no me permiten comentar en otras respuestas, tengo que contaminan este hilo con una nueva respuesta.

    Común de las respuestas de la actividad «se abre dos veces» problema y mis experiencias con estas soluciones (Android 7.1.1):

    1. Deshabilitar el botón que inicia la actividad: Funciona, pero se siente un poco torpe. Si usted tiene varias formas 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), tienes que seguir la pista de la activa/desactiva el estado de varios elementos de la GUI. Además no es muy conveniente para deshabilitar el hecho clic en elementos en una vista de lista, por ejemplo. Así, no es un enfoque universal.
    2. launchMode=»instancia única»: No funciona con startActivityForResult(), se rompe la espalda de navegación con startActivity(), no se recomienda para regular las aplicaciones de manifiesto de Android documentación.
    3. launchMode=»singleTask»: No funciona con startActivityForResult(), no se recomienda para regular las aplicaciones de manifiesto de Android documentación.
    4. FLAG_ACTIVITY_REORDER_TO_FRONT: Rompe de nuevo el botón.
    5. FLAG_ACTIVITY_SINGLE_TOP: No de trabajo, la actividad es abierta dos veces.
    6. FLAG_ACTIVITY_CLEAR_TOP: Este es el único trabajo para mí.

    EDIT: Esto fue para el inicio de las actividades con startActivity(). Cuando se utiliza startActivityForResult() necesito para establecer FLAG_ACTIVITY_SINGLE_TOP y FLAG_ACTIVITY_CLEAR_TOP.

    • FLAG_ACTIVITY_SINGLE_TOP me funciona
    • FLAG_ACTIVITY_CLEAR_TOP: Este es el único trabajo para mí en Android 7.1.1
    • Estoy usando «FLAG_ACTIVITY_REORDER_TO_FRONT» y se está trabajando muy bien y el botón de retroceso también actúa normal. ¿Qué fue exactamente lo que quieres decir por «Saltos» botón de atrás»? Podrían aclarar en que?
    • He encontrado que «REORDENAR» la bandera tenía un error… y no fue reordenación en KitKat. Sin embargo, he comprobado que en Lollipop y Pastel, se está trabajando bien.
  5. 5

    Digamos que @wannik es correcto pero si tenemos más de 1 botón de llamada de una misma acción escucha y haga clic en dos botones una vez casi el mismo tiempo antes de comenzar la siguiente actividad…

    Por lo que es bueno si usted 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 para volver al estado:

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

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

    Si usted establezca enabled a false en el detector de llama a ver otro botón usando el mismo oyente todavía estará habilitada. Así que para estar seguro de que la escucha de la acción no es llamado dos veces usted necesita tener algo global que desactiva todos los llamamientos de la escucha(no importa si es nueva instancia o no)

    ¿Cuál es la diferencia entre mi respuesta y a los demás?

    Que están pensando en la manera correcta, pero ellos no están pensando para el futuro regreso a la misma instancia de la actividad de llamadas 🙂

    • servoper, gracias por su investigación. Esta pregunta ha sido ya resuelto, cómo siempre su respuesta también parece prometedor para la situación en la que te dijo. Déjame probar y con el resultado 🙂
    • Tengo este problema en uno de mis juegos. He «seleccionar» nivel de globos que tienen el mismo oyente y las vistas son sólo diferentes por etiquetas. Así que si lo rápido que elegir a dos globos se inicia dos actividades. Sé que debido a la nueva actividad se inicia sonido.. y en este caso, se reproduce el sonido dos veces… pero se puede comprobar haciendo clic en la espalda que le lleve a la actividad anterior
    • Esto no es suficiente. Usted necesidad de utilizar un synchronized(mIsClicked) {...} así a ser 100% seguro.
    • Que no es necesario 🙂
    • usted no necesita un bloque sincronizado, porque esto es todo el Hilo Principal…
    • Sólo porque ocurre para estar seguros en un Android no es hacer un buen código. Si era una clase independiente tendría que ser documentado como no seguro para subprocesos.
    • Hay una razón por la interfaz de usuario Android (e iOS UIKit) código Principal del Hilo, precisamente para que usted no tiene que preocuparse acerca de lo que es seguro para subprocesos, es la Principal Hilo Seguro por diseño. Eso es cómo se hacen las cosas en Android (e iOS). Usted sólo tiene que preocuparse de roscado cuando en realidad se está utilizando threading, que el OP no lo es. La adición de un bloque sincronizado en esa llamada sería un completo desperdicio de código de bytes y en última instancia de la CPU. No puede hacer clic en un «botón» de un subproceso en segundo plano, hay una y sólo una de Lanzadera para eso, es el hilo Principal, así que no, no es necesario hacer «un buen código».
    • No está claro cuál es el OP está haciendo, y él ya se ha mencionado es la ejecución de algunos de llamada de servicio web que parece ser asincrónico, ya que permite que el botón esté pulsado dos veces. Quién sabe por dónde va a comprobar que la variable? Yo no sincronizar en mi código, ya que private significa que yo soy totalmente responsable de ella, pero no me ciegamente decirle a alguien a hacer lo mismo, especialmente si la pregunta es sobre algo tan básico.

  6. 5

    Uso de instancia única para evitar la actividad para invocar dos veces.

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

    Era sólo trabajo para mí cuando startActivity(intent)

    intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    • pero no funciona para startActivityForResult
    • ¿has probado mediante la adición de este android:launchMode = "singleInstance" en el archivo de Manifiesto de la etiqueta de actividad?
  8. 3

    Creo que van sobre cómo solucionar el problema de la manera equivocada. Generalmente es una mala idea para una actividad de hacer ejecutar las solicitudes web en cualquiera de sus inicio del ciclo de vida de los métodos (onCreate(), onResume(), etc). Realmente estos métodos deben ser simplemente utiliza para instanciar e inicializar los objetos de su actividad que se va a utilizar y por lo tanto debe ser relativamente rápido.

    Si necesita realizar una solicitud web, a continuación, hacer esto en un subproceso en segundo plano de su recién lanzado actividad (y mostrar el diálogo de carga en la nueva actividad). Una vez que el fondo subproceso de solicitud completa se puede actualizar la actividad y ocultar el cuadro de diálogo.

    Esto significa, entonces, la nueva actividad debe obtener inicia de inmediato y evitar la doble clic de ser posible.

  9. 3

    Espero que esta ayuda:

     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. 2

    Otros muy muy fácil solución si usted no desea utilizar onActivityResult() es deshabilitar el botón durante 2 segundos (o el tiempo que quieras), no es lo ideal, pero se puede solucionar en parte el problema es que algunos de los casos y el código es sencillo:

       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. 2

    Para esta situación, voy a ir por uno de los dos se acercó, singleTask en manifest.xml O una bandera en la Actividad del onResume() & onDestroy() métodos respectivamente.

    Para la primera solución: yo prefiero usar singleTask para la actividad en el manifiesto, en lugar de singleInstance, como por el uso de singleInstance me di cuenta de que en algunas ocasiones la actividad de creación de una nueva instancia independiente por sí mismo cual resultado de dos aplicaciones independientes de la ventana en la ejecución de aplicaciones en bcakground y extra además de las asignaciones de memoria que el resultado sería una muy mala Experiencia del Usuario cuando el usuario abre la vista de aplicaciones para elegir alguna aplicación para reanudar.
    Así, la mejor manera es tener la actividad definida en el manifest.xml como la siguiente:

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

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


    Para la segundo solución, tienes que definir una variable estática o una preferencia de la variable, 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 se desea iniciar esta actividad, sólo de verificación:

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

    Simplemente mantener una bandera en el botón de método onClick como:

    public boolean oneTimeLoadActivity = false;

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

    Si usted está usando onActivityResult, usted 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;
      }
    }

    Obras en la parte de atrás del botón presionado demasiado porque el código de solicitud es devuelta en el evento.

  14. -1
    myButton.setOnClickListener(new View.OnClickListener() {
          public void onClick(View view) {
          myButton.setOnClickListener(null);
        }
    });
    • Que probablemente no funcione, ya que tendría que declarar como final.
  15. -1

    Utilizar un flag conjunto de variables que to true,
    Compruebe si su verdadero sólo return más realizar la Actividad Llamada.

    También puede utilizar setClickable(falso) uno de ejecutar la Actividad Llamada

    flg=false
     public void onClick(View view) { 
           if(flg==true)
             return;
           else
           { flg=true;
            //perform click}
        } 
    • perform click; wait; flg = false; para cuando volvamos
  16. -1

    Sólo podría reemplazar startActivityForResult y el uso 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);
        }
    }
  17. -1

    //variable para el seguimiento de eventos en tiempo

    private long mLastClickTime = 0;

    2.En onClick comprobar que si la hora actual y por último haga clic en la diferencia de tiempo son menos de lo segundo, entonces no hagas nada(volver)
    los demás van para el evento click

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

    Que usted puede 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);
                }
    
            });

Dejar respuesta

Please enter your comment!
Please enter your name here