Jaka jest różnica między onPause () i onStop () w Android Activites?

149

Z dokumentu na temat Androida tutaj http://developer.android.com/reference/android/app/Activity.html , powiedział, że „Aktywność jest na pierwszym planie” onPause(), a „Aktywność nie jest już widoczna” onStop().

Czy „Aktywność pojawia się na pierwszym planie” nie jest tym samym, co „Aktywność nie jest już widoczna”? Czy możesz mi powiedzieć, jaka jest różnica między nimi?

Michael
źródło
17
+1 za doskonałe pytanie. Ponadto pauseddziałanie jest całkowicie żywe (zachowuje wszystkie informacje o stanie i członkach oraz pozostaje połączone z menedżerem okien). stoppedAktywność zachowuje również wszelkie informacje o stanie i członek, ale nie jest już przywiązany do window manager.
ateiob

Odpowiedzi:

107

Nie, jeśli jakaś aktywność pojawia się na pierwszym planie, nie musi to oznaczać, że druga aktywność jest całkowicie niewidoczna. Rozważ następujący przypadek:

Aktywność z motywem Theme.Dialog

Tutaj widzimy obie czynności w tym samym czasie. Pierwsze działanie z polami jest zasłonięte przez inne działanie i użytkownik nie może już z nim wchodzić. Jednak jest nadal widoczny ze wszystkimi wynikającymi z tego konsekwencjami.

Pozostaje pytanie, które działanie jest uważane za całkowicie nieprzezroczyste i obejmujące cały ekran, a które nie. Ta decyzja jest podejmowana na podstawie okna zawierającego czynność. Jeśli okno ma flagę windowIsFloatinglub windowIsTranslucent, wówczas uważa się, że działanie nie sprawia, że ​​element bazowy jest niewidoczny, w przeciwnym razie ma i spowoduje wywołanie onStop(). Odpowiedni kod można znaleźć w com.android.server.am.ActivityRecord:

fullscreen = ent != null && !ent.array.getBoolean(
        com.android.internal.R.styleable.Window_windowIsFloating, false)
        && !ent.array.getBoolean(
        com.android.internal.R.styleable.Window_windowIsTranslucent, false);
Malcolm
źródło
10
+1 za świetne wyjaśnienie, skupiające się na widoczności częściowej i całkowitej (nie). Interesujące byłoby poznanie progu procentowego ekranu, który sprawia, że ​​Android decyduje między onPause()a onStop(). Czy to w 100%? Jeśli widoczny jest tylko jeden piksel z poprzedniej czynności, czy nadal onPause()?
ateiob
3
@ateiob Nigdzie nie jest powiedziane, ale myślę, że tak. Zwykle jest to jednak oczywiste, ponieważ większość czynności, które nie wypełniają całego ekranu, używa po prostu jednego ze stylów dialogów dostępnych w systemie.
Malcolm,
1
Dziwne, ale w mojej aplikacji onPause()nie jest w ogóle wywoływane po wyświetleniu okna dialogowego. onPause()jest wywoływana tylko wtedy, gdy naciskam przycisk home . Jak to jest możliwe?
ateiob
To powinna być prawidłowa odpowiedź. Nawiasem mówiąc, na pierwszym planie jest dialog lub działanie?
GMsoF,
3
@GMsoF Aktywność. To jest główny punkt: nie każde okno dialogowe jest w rzeczywistości dialogiem. Możesz sprawić, że działanie będzie wyglądać jak okno dialogowe, więc w rzeczywistości będzie mniejsze niż cały ekran.
Malcolm,
38

Jeśli nadal możesz zobaczyć jakąkolwiek jego część ( Activitypojawiająca się na pierwszym planie albo nie zajmuje całego ekranu, albo jest nieco przezroczysta), onPause()zostanie wywołany. Jeśli nie możesz zobaczyć żadnej jego części, onStop()zostanie wezwany.

Na przykład okno dialogowe ** może nie obejmować całego poprzedniego Activityi byłby to czas na onPause()wywołanie.

** Nie mam tu na myśli okna dialogowego systemu Android, a raczej konceptualnego pomysłu na coś, co wyskakuje i zasłania tylko część ekranu użytkownika. Ta notatka została dodana w celu wyjaśnienia na podstawie komentarza @GMsoF poniżej

nicholas.hauschild
źródło
33
NIE. To jest mylące. Pokazane okno dialogowe nie wywoła funkcji onPause (), ponieważ okno dialogowe używa kontekstu bieżącej czynności, uważa, że ​​aktywność jest żywa.
GMsoF,
6
@GMsoF Wygląda na to, że kiedy powiedziałem dialog, myślałeś, że mam na myśli Dialog, jak w klasie Androida. Jednak to, do czego zmierzałem, jest czymś, co częściowo przesłania pierwsze, Activityco ilustruje ideę, że wszystkie nowe Activitynie muszą całkowicie zakrywać poprzedniego.
nicholas.hauschild
11

Bycie na pierwszym planie oznacza, że ​​działanie jest ukierunkowane na wkład. Na przykład działanie może być widoczne, ale częściowo zasłonięte przez okno dialogowe, na którym jest fokus. W takim przypadku onPause()zostanie wywołany, ale nie onStop(). Kiedy okno dialogowe zniknie, onResume()zostanie wywołana metoda działania (ale nie onStart()).

Ted Hopp
źródło
5
Ten dialog może wprowadzać w błąd. Niech pojawi się okno dialogowe z ostrzeżeniem z głównego wątku UI tego działania, w tym przypadku onPause () nie zostanie wywołana. Tylko wtedy, gdy to okno dialogowe jest wyświetlane z innej aktywności lub innej aplikacji.
Sam003
1
@Zhisheng - zgadzam się z twoim komentarzem. Parafrazowałem tylko temat przewodnika Activites : onPause()jest wywoływany, gdy urządzenie zasypia lub pojawia się okno dialogowe” . Tak jak wyjaśnia ten wątek , dialog niekoniecznie oznacza, że ​​czynność jest wstrzymana (chociaż byłoby to, powiedzmy, działanie pokazane jako okno dialogowe ).
Ted Hopp
9

Praktycznie należy wziąć pod uwagę różnicę między „onPause ()” a „onPause () + onStop ()”.

Ilekroć pojawi się jakaś nowa aktywność i zajmie jakąś część ekranu. Więc Twoja wcześniejsza aktywność jest nadal do pewnego stopnia widoczna. W takim przypadku poprzednio uruchomione działanie nie jest wypychane do stosu wstecznego. Tak więc tutaj wywoływana jest tylko metoda onPause () .

Z drugiej strony, jeśli pojawi się nowa aktywność i zajmie ona cały ekran, tak że poprzednio uruchomiona aktywność zniknie. W takim przypadku Twoja poprzednio uruchomiona aktywność zostanie przeniesiona do Back Stack. Tutaj wywoływane są onPause () + onStop ().

Do streszczeń

onPause () - Ekran jest częściowo pokryty inną nową aktywnością. Aktywność nie jest przenoszona do stosu wstecznego.

onPause () + onStop () - Ekran jest w pełni pokryty inną nową aktywnością. Aktywność zostaje przeniesiona do stosu wstecznego.

Dowiedz się więcej o - Back Stack .

Yash
źródło
0

Krótko mówiąc:

onStop()Metoda cyklu życia poprzedniej czynności jest wywoływana, gdy pokazywana jest inna czynność. Kiedy masz Dialog na szczycie aktywności, onPause()jest wywoływany.

Uwaga : Działania to te elementy, które wypełniają cały ekran.

Uwaga : dialogi nie są działaniami, ponieważ nie wypełniają całkowicie ekranu.

Uddhav Gautam
źródło
0

Napotkałem wiele problemów z metodami onPause i onStop i dlatego wyczyszczę trzy scenariusze, które napotkałem:
1. Po kliknięciu przycisku ostatniej aplikacji nie jest wywoływana żadna metoda cyklu życia, ale wywoływana jest metoda onWindowFocusChanged (boolean hasFocus) z wartością hasFocus przeszedł jako fałsz. W wersji Androida wcześniejszej niż 5, wywoływano metodę onPause po naciśnięciu przycisku ostatniej aplikacji.

2. Gdy pojawi się wyskakujące działanie podobne do działania, jak wspomniał Malcolm , zostanie wywołany przycisk onPause. W przypadku wywołania nowej czynności, która zajmuje cały ekran, przy poprzedniej czynności wywoływana jest funkcja onStop. Okno dialogowe uprawnień systemu Android powoduje również wywołanie funkcji onPause.

3.Jeśli ekran przekroczy limit czasu aktywności, zostanie wywołane onPause. Po pewnym czasie, jeśli nie otworzysz ekranu, zostanie wywołane onStop.

Również jedna ważna rzecz wymieniona przez ateiob, która uzupełnia odpowiedź

Wstrzymana aktywność jest całkowicie aktywna (zachowuje wszystkie informacje o stanie i członku oraz pozostaje połączona z menedżerem okien). Zatrzymana aktywność zachowuje również wszystkie informacje o stanie i członkach, ale nie jest już dołączona do menedżera okien


Mam nadzieję, że to pomoże.

royatirek
źródło
0

za każdym razem, gdy rozpocznie się nowa AKTYWNOŚĆ, poprzednia czynność onPausezostanie wyzywająco wywołana w każdych okolicznościach.

w rzeczywistości będą dwie okoliczności:

1- część poprzedniej czynności jest widoczna lub nowa aktywność jest przejrzysta: tylko onPause zostanie wywołana.

2 - poprzednia aktywność jest całkowicie objęta nową aktywnością: zarówno onPausei onStopbędzie nazywana

---- Dobrze jest podać kilka uwag:

UWAGA 1: jeśli okno dialogowe rozpocznie się nad działaniem, ŻADNE z onPauselub onStopnie zostanie wywołane.

UWAGA 2: jeśli jest to działanie, którego motywem przewodnim jest okno dialogowe, zachowanie będzie takie jak normalne działanie.

UWAGA 3: najwyraźniej okno dialogowe systemu, takie jak okno dialogowe uprawnień, ponieważ spowoduje to marshmallow onPause.

Amir Ziarati
źródło
-5

Tak, staram się zrozumieć i mogę to wyjaśnić poniżej:

Istnieją 2 działania: Aktywność A i Aktywność B.

public class ActivityA extends Activity implements OnClickListener {

// button
private Button mBtnChangeActivity;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_a);
    initialize();
    setEvent();
}

private void initialize() {
    Log.i("Activity A", "Initialize()");
    mBtnChangeActivity = (Button) findViewById(R.id.btn_change_activity);
}

private void setEvent() {
    Log.i("Activity A", "setEvent()");
    mBtnChangeActivity.setOnClickListener(this);
}

@Override
protected void onStart() {
    super.onStart();
    Log.i("Activity A", "onStart");
}

@Override
protected void onResume() {
    super.onResume();
    Log.i("Activity A", "onResume");
}

@Override
protected void onPause() {
    super.onPause();
    Log.i("Activity A", "onPause");
}

@Override
protected void onStop() {
    super.onStop();
    Log.i("Activity A", "onStop");
}

@Override
protected void onDestroy() {
    super.onDestroy();
    Log.i("Activity A", "onDestroy");
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.btn_change_activity:
        Intent activityB = new Intent(this, ActivityB.class);
        startActivity(activityB);
        break;
    default:
        break;
    }
}

Oto aktywność B. Postępuj zgodnie z moim komentarzem w kodzie

public class ActivityB extends Activity implements OnClickListener {

// button
private Button mBtnChangeActivity;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_a);
    initialize();
    setEvent();
    // if call finish() here, activityA will don't stop, just pause
    // Activity A will call onStop() when Activity B call onStart() method
    finish();
}

private void initialize() {
    Log.i("Activity B", "Initialize()");
    mBtnChangeActivity = (Button) findViewById(R.id.btn_change_activity);
}

private void setEvent() {
    Log.i("Activity B", "setEvent()");
    mBtnChangeActivity.setOnClickListener(this);
}

@Override
protected void onStart() {
    super.onStart();
    Log.i("Activity B", "onStart");
}

@Override
protected void onResume() {
    super.onResume();
    Log.i("Activity B", "onResume");
}


@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.btn_change_activity:
        finish();
        break;
    default:
        break;
    }
}
}

Mam nadzieję, że to jasne

Lê Quốc Tiến
źródło
zawsze staraj się wyjaśnić, że ma to sens
Alexander Zaldostanov