Pourquoi mon onResume est appelé deux fois?
en gros, C'est ce que je fais
1) Régler 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 Monactivité à 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) avoir MyActivity tourner sur l'écran si elle n'est pas sur
@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 juste quand Monactivité est ouverte, c'est le flux qui fait:
onCreate/onNewIntent -> onResume -> onPause - >onResume
Je ne sais pas pourquoi il fait une onPause tout de suite. Je remarque que cela se produit uniquement lorsque le dépistage est activé par les drapeaux. Personne ne sait pourquoi cela se produit? Y a-t-il un moyen de prévenir ce comportement?
13 réponses
juste au cas où quelqu'un d'autre tomberait dans cette situation, je semble remarquer ce comportement seulement quand je gonfle des fragments à l'intérieur d'une activité via XML layout. Je ne sais pas si ce comportement se produit aussi avec la version de la bibliothèque de compatibilité de Fragments (j'utilise android.App.Fragment)
il semble que l'activité appellera Activity#onResume
une fois avant d'appeler Fragment#onResume
à tout fragment ajouté, puis appellera à nouveau Activity#onResume
.
- Activité: onCreate
- Fragment: onAttach
- activité: onAttachFragments
- Fragment: onCreate
- activité: onStart
- activité: onResume
- Fragment: onResume
- activité: onResume
Si vous avez ES File Explorer
puis FORCER l'ARRÊT . 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 en quelque sorte appelé après que l'activité a été créée.. quelque chose interrompait mon application.
et ce seulement arrive 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 post 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 I force stop ES File Explorer , ce comportement de hoquet ne se produit plus... il est frustrant de savoir après avoir essayé beaucoup d'autres les solutions proposées. Alors méfiez-vous de toute autre application interrompant comme celle-ci.
j'ai fait des recherches à ce sujet pendant un certain temps parce que sur internet il n'y a 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 quand il se produit.
onPause-onResume-onPause-onResume
se produit juste à chaque fois, quand l'application commence la première fois après l'installation. Vous pouvez simplement invoquer ce comportement en faisant n'importe quel changement dans le code et la redirection (qui inclut la recompilation) l'application de votre IDE.
peu importe si vous utilisez AppCompat libs ou non. J'ai testé les deux cas et le comportement continue.
Note: testé sur Android Marshmallow.
j'ai emprunté le code de ce fil sur le cycle de vie des fragments et de l'activité et il est ici (il suffit de copier, coller, déclarer l'activité dans le manifeste et courir 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()");
}
}
}
Je ne sais pas avec certitude ce qui se passe, mais je soupçonne que votre activité est redémarrée parce que la mise en marche de l'écran est traitée par le système comme un changement de configuration. Vous pouvez essayer d'enregistrer la configuration sur chaque appel à onResume
pour voir si c'est ce qui se passe et, si c'est le cas, ce qui est en train de changer. Vous pouvez alors modifier le Manifeste pour dire au système que votre activité gérera le changement par elle-même.
protected void onResume() [
super.onResume();
Configuration config = new Configuration();
config.setToDefaults();
Log.d("Config", config.toString());
. . .
}
j'avais un problème similaire, et mon problème était qu'à 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é l'onResume() deux fois. Il a fonctionné comme prévu après que je l'ai changé en juste:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.friends); <-- 'super.' removed
}
J'espère que ça aidera.
j'ai le même problème. Ma situation était la suivante activité courante s'étend activité principale CurrentFragment s'étend MainFragment
j'ai été l'ouverture CurrentActivity avec l'intention, comme d'habitude. Dans le numéro CurrentAcitivity , Je remplaçais CurrentFragment.
Cycle de vie a été: 1. onResume MainActivity 2. onsume CurrentActivity 3. onResume MainFragment 4. onResume CurrentFragment
fait appel Àpause automatiquement, et ensuite à nouveau
- onResume MainActivity
- onResume CurrentActivity
- onResume MainFragment
- onResume CurrentFragment
je décide de tester à nouveau le tout et après quelques heures passées à essayer et en jouant j'ai trouvé le problème de racine. Dans MainFragment onStart j'appelaisstartactivityforresult à chaque fois (dans mon cas, android popup pour allumer le Wifi) qui était appelé onPause sur MainFragment. Et nous savons tous qu'après onPause suivant est onResume.
donc ce n'est pas un bug Android, c'est seulement le mien: -)
Heureux cycle de vie de debuging!
j'ai aussi rencontré cette séquence onresume-onpause-onresume (sur 4.1.2 et ci-dessus, mais je ne l'ai pas fait sur 2.3). Mon problème était lié à la manipulation de wakelock: j'ai accidentellement oublié de libérer un wakelock et sa réacquisition a causé une erreur avec un message "wakelock finalisé alors qu'il est encore détenu". Ce problème a conduit à onPause étant appelé immédiatement après onResume et a entraîné un comportement défectueux.
ma suggestion est: vérifiez les erreurs dans le journal, ceux pourraient être liés à cette question.
un autre indice: allumer l'écran peut être un peu plus délicat que d'utiliser simplement des indicateurs de fenêtre. Vous pouvez 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é activé et de lancer l'activité désirée seulement après: https://stackoverflow.com/a/16346369/875442
il semble que l'utilisation de Activity
de la bibliothèque de support sauve et restaure l'instance automatiquement. Par conséquent, ne faites votre travail que si savedInstanceState
est null
.
je viens de tomber sur ceci, et il semble que getWindow().addFlags()
et modifier Window
propriétés en général pourrait être un coupable.
quand mon code est comme ceci
@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 quand je supprime requestWindowFeature()
, il est appelé seulement une fois.
je pense que vous devriez jeter un oeil à cette question: Nexus 5 d'aller dormir, le mode d'activité du cycle de vie buggy Vous devriez trouver des fils
Fondamentalement, beaucoup de choses peuvent déclencher cette. Certains processus de CV qui perd la concentration peut le faire. Quelques applications vont provoquer ça aussi. La seule façon de faire face est de bloquer la double course. Notez qu'il y aura aussi 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 solide moyen de prévenir de telles choses. Ça bloquera les doubles CV. Mais, il bloquera aussi deux CV qui préservent la mémoire. Donc, si vous avez juste perdu la concentration et il n'a pas besoin de reconstruis tes affaires. Il bloque aussi. Ce qui pourrait être un avantage clairement, puisque si vous utilisez le CV pour contrôler certains changements sur la mise au point, vous seulement se soucient réellement si vous avez besoin de reconstruire ce truc à cause de la mise au point. Puisque les pré-draw listeners ne peuvent être appelés que par un seul thread et qu'ils doivent être appelés en séquence, le code ici ne sera lancé qu'une seule fois. Jusqu'à ce que quelque chose détruise toute l'activité et renvoie le resumeblock à false.
j'ai également fait face à cette question c'est à cause de fragments..
le nombre de fragments que vous avez dans l'activité onResume()
appellent le nombre de fois. pour surmonter j'ai utilisé des variables de drapeau dans SharedPrefrences
si vous essayez de demander des permissions à chaque fois qu'il peut causer de tels problèmes, il suffit de vérifier si vous les avez déjà accordées
requestPermissions
peut causer:
onCreate
onStart
onResume
onPause
onResume