web-dev-qa-db-fra.com

Pourquoi mon onResume est-il appelé deux fois?

En gros, c'est ce que je fais

1) Configurez AlarmManager pour exécuter BroadcastReceiver (BCR)

Intent intent = new Intent(m_Context, BCR.class);  
intent.putExtras(extras);  
PendingIntent pendingIntent = PendingIntent.getBroadcast(m_Context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);  
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, StartTime, pendingIntent)  

2) Démarrer MyActivity à partir de BCR 

@Override  
public void onReceive(Context context, Intent intent) {  
    Intent newIntent = new Intent(context, MyActivity.class);
    newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);  
    context.startActivity(newIntent);  
}

3) MyActivity allume l'écran s'il n'est pas allumé

@Override  
public void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState); 
    getWindow().addFlags(LayoutParams.FLAG_DISMISS_KEYGUARD);
    getWindow().addFlags(LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    getWindow().addFlags(LayoutParams.FLAG_TURN_SCREEN_ON);
    setContentView(R.layout.myactivity);  
} 

@Overide  
protected void onNewIntent(Intent intent) {  
    super.onNewIntent(intent);  
}  

Pour une raison quelconque, je remarque que lorsque MyActivity est ouvert, son flux est le suivant: 

onCreate/onNewIntent -> onResume -> onPause -> onResume

Je ne sais pas pourquoi on fait une pause tout de suite. Je remarque que cela ne se produit que lorsque l'écran est activé par les drapeaux. Est-ce que quelqu'un sait pourquoi cela se produit? Y a-t-il un moyen d'empêcher ce comportement?

40
Huy T

Juste au cas où quelqu'un d'autre se heurterait à cela, il semble que je ne remarque ce comportement que lorsque je gonfle des fragments à l'intérieur d'une activité via une présentation XML. Je ne sais pas si ce problème se produit également avec la version de bibliothèque de compatibilité de Fragments (j'utilise Android.app.Fragment) 

Il semble que l'activité appelle Activity#onResume une fois avant d'appeler Fragment#onResume aux fragments ajoutés, puis appelle à nouveau Activity#onResume.

  1. Activité: onCreate
  2. Fragment: onAttach
  3. Activité: onAttachFragments
  4. Fragment: onCreate
  5. Activité: onStart
  6. Activité: onResume
  7. Fragment: onResume
  8. Activité: onResume
27
ainesophaur

Si vous avez ES File Explorer, alors FORCE STOP le. D'une manière ou d'une autre, ils interrompent le cycle de vie de votre application (les commentaires suggèrent une sorte de superposition)}.

Mon problème avec onResume causé deux fois était parce que onPause était appelé d'une manière ou d'une autre après la création de l'activité. Quelque chose interrompait mon application.

Et ceci seulement se produit après avoir été ouvert pour le première fois après l'installation ou construit à partir du studio.

J'ai eu le indice d'un autre message et j'ai découvert que c'était à cause de ES File Explorer. Pourquoi onResume () semble-t-il être appelé deux fois?

Dès que je force arrête ES File Explorer, ce problème ne se produit plus ... il est frustrant de le savoir après avoir essayé de nombreuses autres solutions proposées. Alors méfiez-vous de toute autre interruption application comme celle-ci.

16
TWL

Je faisais des recherches à ce sujet pendant un moment car sur Internet, il n’ya aucune mention de ce comportement étrange. Je n'ai pas de solution pour surmonter ce comportement obscur, mais j'ai trouvé un scénario exact lorsque cela se produit.

onPause-onResume-onPause-onResume se produit à chaque fois, lorsque l'application démarre pour la première fois après l'installation. Vous pouvez simplement invoquer ce comportement en modifiant le code et en réexécutant l'application (ce qui inclut la recompilation) à partir de votre IDE.

Peu importe si vous utilisez ou non les bibliothèques AppCompat. J'ai testé les deux cas et le comportement continue. 

Remarque: Testé sur Android Marshmallow.

J'ai emprunté le code de ce fil sur le cycle de vie des fragments et des activités et le voici (il suffit de copier, coller, déclarer une activité dans manifest et exécuter Forest run):

import Android.app.Activity;
import Android.app.Fragment;
import Android.app.FragmentTransaction;
import Android.content.Context;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.TextView;

public class TestActivity extends Activity {

    private static final String TAG = "ACTIVITY";

    public TestActivity() {
        super();
        Log.d(TAG, this + ": this()");
    }

    protected void finalize() throws Throwable {
        super.finalize();
        Log.d(TAG, this + ": finalize()");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, this + ": onCreate()");


        TextView tv = new TextView(this);
        tv.setText("Hello world");
        setContentView(tv);

        if (getFragmentManager().findFragmentByTag("test_fragment") == null) {
            Log.d(TAG, this + ": Existing fragment not found.");
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.add(new TestFragment(), "test_fragment").commit();
        } else {
            Log.d(TAG, this + ": Existing fragment found.");
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, this + ": onStart()");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, this + ": onResume()");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d(TAG, this + ": onPause()");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG, this + ": onStop()");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, this + ": onDestroy()");
    }


    public static class TestFragment extends Fragment {

        private static final String TAG = "FRAGMENT";

        public TestFragment() {
            super();
            Log.d(TAG, this + ": this() " + this);
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, this + ": onCreate()");
        }


        @Override
        public void onAttach(final Context context) {
            super.onAttach(context);
            Log.d(TAG, this + ": onAttach(" + context + ")");
        }

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            Log.d(TAG, this + ": onActivityCreated()");
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Log.d(TAG, this + ": onCreateView()");
            return null;
        }

        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            Log.d(TAG, this + ": onViewCreated()");
        }

        @Override
        public void onDestroyView() {
            super.onDestroyView();
            Log.d(TAG, this + ": onDestroyView()");
        }

        @Override
        public void onDetach() {
            super.onDetach();
            Log.d(TAG, this + ": onDetach()");
        }

        @Override
        public void onStart() {
            super.onStart();
            Log.d(TAG, this + ": onStart()");
        }

        @Override
        public void onResume() {
            super.onResume();
            Log.d(TAG, this + ": onResume()");
        }

        @Override
        public void onPause() {
            super.onPause();
            Log.d(TAG, this + ": onPause()");
        }

        @Override
        public void onStop() {
            super.onStop();
            Log.d(TAG, this + ": onStop()");
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d(TAG, this + ": onDestroy()");
        }
    }

}
7
matusalem

si vous essayez de demander des autorisations chaque fois que cela peut causer de tels problèmes, vérifiez simplement si vous les avez déjà accordées.

requestPermissions peut le causer:

onCreate
onStart
onResume
onPause
onResume
6
user924

Je ne sais pas exactement ce qui se passe, mais je soupçonne que votre activité est en cours de redémarrage car la configuration de l'écran est traitée par le système comme un changement de configuration. Vous pouvez essayer de consigner la configuration à chaque appel avec onResume pour voir si c'est ce qui se passe et, le cas échéant, ce qui change réellement. Vous pouvez ensuite modifier le manifeste pour indiquer au système que votre activité gérera elle-même le changement.

protected void onResume() [
    super.onResume();
    Configuration config = new Configuration();
    config.setToDefaults();
    Log.d("Config", config.toString());
    . . .
}
5
Ted Hopp

J'ai eu un problème similaire, et mon problème était que, à la méthode onCreate (), je faisais:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    super.setContentView(R.layout.friends);  <-- problem
}

Mon appel à "super". a déclenché le onResume () deux fois. Cela a fonctionné comme prévu après l'avoir modifié pour simplement:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.friends);  <-- 'super.' removed
}

J'espère que ça aide.

2
Victor Lee

J'ai le même problème. Ma situation était la suivante CurrentActivity s'étend MainActivityCurrentFragment s'étend MainFragment

J'ouvrais CurrentActivity avec l'intention comme d'habitude. Dans onCreate CurrentAcitivity, je remplaçais CurrentFragment.

Le cycle de vie était: 1. onResume MainActivity 2. onResume CurrentActivity 3. onResume MainFragment 4. onResume CurrentFragment

appelé onPause automatiquement, puis à nouveau

  1. onResume MainActivity
  2. onResume CurrentActivity
  3. fragment principal
  4. onResume CurrentFragment

Je décide de tout retester et après quelques heures passées à essayer et à jouer, j'ai trouvé le problème fondamental. Dans MainFragment onStart, j’appelais startActivityForResult à chaque fois (dans mon cas, le popup Android pour activer le Wifi) qui était appelé à la pause sur MainFragment. Et nous savons tous qu'après onPause, on est en reprise. 

Donc ce n'est pas un bug Android, ce n'est que le mien :-) 

Bon débogage de cycle de vie!

2
msamardzic

J'ai également rencontré cette séquence onresume-onpause-onresume (sur les versions 4.1.2 et supérieures, mais je ne l'ai pas expérimentée sur la version 2.3). Mon problème était lié à la manipulation de wakelock: j'ai accidentellement oublié de libérer un wakelock et le réacquérir a provoqué une erreur avec le message "WakeLock finalisé tant qu'il est toujours en attente". Ce problème a abouti à l'appel de onPause immédiatement après onResume et a entraîné un comportement défectueux.

Ma suggestion est la suivante: vérifiez les erreurs dans le journal, celles-ci pourraient être liées à ce problème.

Autre astuce: allumer l'écran pourrait être un peu plus compliqué que de simplement utiliser des indicateurs de fenêtre. Vous voudrez peut-être vérifier cette réponse ici - il vous suggère de configurer un récepteur pour vérifier si l'écran a déjà été allumé et de lancer l'activité souhaitée uniquement après: https://stackoverflow.com/a/16346369/875442

0
Levente Dobson

Je viens de le rencontrer, et il semble que getWindow().addFlags() et le réglage de Window propriétés en général pourraient être un coupable.

Quand mon code est comme ça

@Override
protected void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_generic_fragment_Host);
    // performing fragment transaction when instance state is null...

onResume() est déclenché deux fois, mais lorsque je supprime requestWindowFeature(), il n'est appelé qu'une fois.

0
Actine

J'ai eu le même problème. Le mien était pour ce code en runtime

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Je viens de le mettre en manifeste

Android:screenOrientation="landscape"

plus de problème, appelez onCreate et onResume deux fois.

0
Boris Karloff

Il semble que l'utilisation de Activity à partir de la bibliothèque de support enregistre et restaure l'instance automatiquement. Par conséquent, ne faites votre travail que si savedInstanceState est null.

0
yazjisuhail

Fondamentalement, beaucoup de choses peuvent déclencher cela. Certains processus de reprise qui perd le focus peuvent le faire. Quelques applications le feront aussi. La seule façon de faire face est de bloquer la double course. Notez que cela fera également une pause errante pour faire bonne mesure.

    boolean resumeblock = false;

    @Override
    protected void onResume() {
        super.onResume();
        sceneView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                sceneView.getViewTreeObserver().removeOnPreDrawListener(this);
                if (resumeblock) return false;
                resumeblock = true;

                //Some code.

                return false;
            }
        });
    }

C'est un moyen efficace d'éviter de telles choses. Il bloquera les doubles reprises. Mais, il va également bloquer deux CV qui préservent la mémoire. Donc, si vous venez de perdre votre concentration et qu'il n'a pas besoin de reconstruire vos données. Ça va bloquer ça aussi. Ce qui pourrait être un avantage clair, car si vous utilisez le CV pour contrôler certaines modifications par rapport à la mise au point, vous vous inquiétez que seulement si vous avez besoin de la reconstruire à cause de la mise au point. Etant donné que les écouteurs de pré-tirage ne peuvent être appelés que par le seul thread et qu'ils doivent être appelés l'un après l'autre, le code ne sera exécuté qu'une fois. Jusqu'à ce que quelque chose détruise correctement toute l'activité et redonne à resumeblock la valeur false.

0
Tatarize

comme @TWL a dit ES File Explorer Était le problème pour moi! La désinstallation de l'application a résolu le problème . Lorsque ce ES File Explorer a été installé, onStart() -> onResume() -> onPause() -> onResume() .. était le problème .onResume() était appelé 2'ce.

0
Pramod P K

Je pense que vous devriez jeter un coup d’œil à cette question: Nexus 5 passer en mode veille rend le cycle de vie de l’activité bogué Vous devriez trouver des pistes

j'ai également été confronté à ce problème en raison de fragments ........ le nombre de fragments que vous avez dans l'activité onResume() appellera ce nombre de fois. pour surmonter j'ai utilisé des variables de drapeau dans SharedPrefrences

0
Sanju Baghla