2013-04-16 3 views
36

В принципе, это то, что я делаюПочему мой onResume называется дважды?

1) Установить AlarmManager выполнить 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) Запустить MyActivity от 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 поворот на экране, если его нет на

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

Для некоторых Причина, я заметил, что правильно, когда открыт MyActivity, это поток идет как:

OnCreate/onNewIntent -> onResume -> OnPause -> onResume

Я не знаю, почему он делает OnPause сразу. Я замечаю, что это происходит только тогда, когда экранирование включается флагами. кто-нибудь знает, почему это произошло? Можно ли предотвратить такое поведение?

+0

Является ли ваша деятельность определенной ориентацией, такой как портрет или пейзаж? – twaddington

+0

Экран «Ориентация» установлен в портрет для MyActivity в манифесте. –

ответ

5

Я не знаю точно, что происходит, но я подозреваю, что ваша деятельность перезапускается, потому что установка экрана на экране рассматривается системой как изменение конфигурации. Вы можете попытаться выполнить регистрацию конфигурации при каждом вызове до onResume, чтобы узнать, что происходит, и если да, то что на самом деле меняется. Затем вы можете изменить манифест, чтобы сообщить системе, что ваша деятельность будет обрабатывать изменение самостоятельно.

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

Не похоже, что между двумя onResumes происходят изменения конфигурации. –

+0

@HuyT - Система помещает что-либо в файл журнала, который может указывать на то, что происходит? –

+0

Единственное, что я вижу, это то, что ActivityManager пытается отобразить Activity, а PowerManagerService просыпается от сна только после onPause. Есть ли способ заставить это произойти до onPause? –

26

Только в случае, если кто-то работает в этом, я, кажется, заметить это поведение только тогда, когда я надуть фрагменты внутри деятельности с помощью макета XML. Я не знаю, связано ли это с версией библиотеки совместимости с фрагментами (я использую android.app.Fragment)

Кажется, что операция вызовет Activity#onResume один раз перед вызовом в любые добавленные фрагменты, а затем снова вызовет Activity#onResume.

  1. активность: OnCreate
  2. Фрагмент: onAttach
  3. активность: onAttachFragments
  4. Фрагмент: OnCreate
  5. активность: OnStart
  6. активность: onResume
  7. Фрагмент: onResume
  8. активность: onResume
+5

идеи о том, как преодолеть это? – Shai

0

Я также столкнулся с этой последовательностью onresume-onpause-onresume (на 4.1.2 и выше, но я не испытал этого на 2.3). Моя проблема была связана с обработкой wakelock: я случайно забыл выпустить wakelock и снова вызвал ошибку, вызвав сообщение с сообщением «WakeLock финализировалось, пока все еще удерживается». Эта проблема привела к тому, что onPause вызывается сразу после onResume и приводит к ошибочному поведению.

Мое предложение: проверить наличие ошибок в журнале, это может быть связано с этой проблемой.

Еще один намек: включение экрана может быть более сложным, чем просто использование флажков с окнами.Вы можете проверить этот ответ здесь - он предлагает вам настроить приемник, чтобы проверить, включен ли экран и запустить его только после: https://stackoverflow.com/a/16346369/875442

0

Кажется, что использование Activity из библиотеки поддержки сохраняет и автоматически восстанавливает экземпляр. Поэтому делайте свою работу только в том случае, если savedInstanceState: null.

2

У меня была аналогичная проблема, и проблема была, что в OnCreate() метод, я делал:

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

Мой призыв к «супер». запускал onResume() дважды. Он работал по назначению после того, как я сменил его на просто:

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

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

+0

Вы сохранили много своего времени с этим комментарием. ти! – Dani

+5

Это не устраняет проблему. Как люди могут на самом деле продвигать этот не-смысл? – Johny19

0

Я просто столкнулся с этим, и кажется, что getWindow().addFlags() и настройка Window объектов в целом может быть преступником.

Когда мой код, как этот

@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() запускается в два раза, но когда я удалить requestWindowFeature(), это только раз.

5

Я занимался этим некоторое время, потому что в Интернете нет никаких упоминаний об этом странном поведении. У меня нет решения, как преодолеть это поведение с темной стороны, но я нашел точный сценарий, когда это, безусловно, происходит.

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

Независимо от того, используете ли вы AppCompat libs или нет. Я тестировал оба случая, и поведение продолжается.

Примечание: Испытано на Android Зефир.

я позаимствовал код из this thread about fragment and activity lifecycle и здесь (просто скопировать, вставить, объявить активность в манифесте и запустить Forest перспективе):

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

} 
+0

У меня точно такая же проблема, если использовать галактическую галактику samsung 4 .. вы нашли какую-нибудь работу? – tsiro

+0

Я до сих пор не нашел обходного пути. Я остановил использование уязвимых операций (например, запуск потоков и т. Д.) В 'onResume' и' onPause'. Я переместил их в 'onStart' и' onStop'. – matusalem

+0

Я сделал точно то же самое сегодня ... – tsiro

8

Если у вас есть ES File Explorer, FORCE-STOP это. Так или иначе, они прерывают жизненный цикл вашего приложения.

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

И это происходит только после того, как открыл для впервые после установки или построен из студии.

Я получил CLUE из другого сообщения и узнал, что это из-за ES File Explorer. Why does onResume() seem to be called twice?

Как только я пытаюсь остановить «ES File Explorer», это поведение икоты больше не происходит ... очень сложно узнать, попробовав так много других предлагаемых решений.

+1

Возможно, потому что ES Explorer создает наложение для сбора данных аналитики при запуске любого приложения. Это по существу приведет к смене фокуса, что может вызвать дублирование пауз и возобновление триггеров – anandbibek

2

У меня есть схожая проблема. Моя ситуация была следующая CurrentActivity расширяет MainActivity CurrentFragment Расширяет MainFragment

Я открывала CurrentActivity с целью, как обычно. In onCreate CurrentAcitivity Я заменял CurrentFragment.

Жизненный цикл был: 1. onResume MainActivity 2. onResume CurrentActivity 3. onResume MainFragment 4. onResume CurrentFragment

называется OnPause автоматически, и после этого снова

  1. onResume MainActivity
  2. onResume CurrentActivity
  3. onResume MainFragment
  4. onResume CurrentFragment

Я решил повторно проверить все, и после нескольких часов, проведенных пытается играть я нашел корень проблемы. В MainFragment onStart я каждый раз вызывал startActivityForResult (в моем случае всплывающее окно Android для включения Wi-Fi), которое вызывало onPause на MainFragment. И все мы знаем, что после onPause next onResume.

Таким образом, ее не Android ошибка, это только мое :-)

Счастливый жизненный цикл отладки!

0

В принципе, многие вещи могут вызвать это. Некоторые процессы возобновления, которые теряют фокус, могут это сделать. Несколько приложений вызовут это тоже. Единственный способ справиться - заблокировать двойную работу. Заметьте, это также приведет к ошибочной паузе, брошенной для хорошей меры.

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

Это надежный способ предотвратить такие вещи. Он будет блокировать двойные резюме. Но он также блокирует два резюме, которые сохраняют память. Поэтому, если вы просто потеряли фокус, и вам не нужно перестраивать ваши вещи. Это тоже заблокирует. Что может быть полезно, потому что, если вы используете резюме для контроля над некоторыми изменениями по фокусу, вы только действительно заботитесь, если вам нужно перестроить этот материал из-за фокуса. Поскольку прослушиватели предварительного рисования могут быть вызваны только одним потоком, и их необходимо вызвать последовательно, код здесь будет запускаться только один раз. До тех пор, пока что-то не уничтожит всю активность и не вернет returnblock в false.

0

Я также столкнулся с этой проблемой, это из-за фрагментов .. количество фрагментов, которые у вас есть в действии onResume() будет называть это количество раз.для преодоления я использовал переменные флага в SharedPrefrences

Смежные вопросы