Sự khác biệt giữa onPause () và onStop () của Android Activites là gì?


149

Từ tài liệu android tại đây http://developer.android.com/reference/android/app/Activity.html , thông báo 'Hoạt động đi vào tiền cảnh' sẽ gọi onPause()và 'Hoạt động không còn hiển thị' sẽ gọi onStop().

Không phải 'Hoạt động đi vào nền trước' giống như 'Hoạt động không còn hiển thị'? Bạn có thể vui lòng cho tôi biết sự khác biệt giữa chúng là gì?


17
+1 cho một câu hỏi xuất sắc. Ngoài ra, một pausedhoạt động hoàn toàn sống động (nó duy trì tất cả thông tin về trạng thái và thành viên và vẫn được đính kèm với trình quản lý cửa sổ). Một stoppedhoạt động cũng giữ lại tất cả thông tin của tiểu bang và thành viên, nhưng không còn được đính kèm window manager.
ateiob

Câu trả lời:


107

Không, nếu một số hoạt động xuất hiện trước, điều đó không nhất thiết có nghĩa là hoạt động kia hoàn toàn vô hình. Hãy xem xét trường hợp sau:

Hoạt động với chủ đề Theme.Dialog

Ở đây chúng tôi thấy cả hai hoạt động cùng một lúc. Hoạt động đầu tiên với các trường bị che khuất bởi một hoạt động khác và người dùng không còn có thể tương tác với nó. Tuy nhiên, nó vẫn được nhìn thấy với tất cả các hậu quả kết quả.

Điều đó đặt ra một câu hỏi hoạt động nào được coi là hoàn toàn mờ đục và bao trùm toàn bộ màn hình và hoạt động nào không. Quyết định này dựa trên cửa sổ chứa hoạt động. Nếu cửa sổ có cờ windowIsFloatinghoặc windowIsTranslucent, thì nó được coi là hoạt động không làm cho các công cụ cơ bản trở nên vô hình, nếu không nó sẽ và sẽ onStop()được gọi. Mã liên quan có thể được tìm thấy trong 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);

10
+1 cho một lời giải thích tuyệt vời, tập trung vào khả năng hiển thị một phần so với tổng (trong). Sẽ rất thú vị khi biết tỷ lệ phần trăm ngưỡng của màn hình khiến Android quyết định giữa onPause()onStop(). Có phải là 100%? Nếu chỉ có một pixel từ hoạt động trước đó hiển thị, nó vẫn còn onPause()?
ateiob

3
@ateiob Không nói đâu, nhưng tôi nghĩ vậy. Tuy nhiên, điều này thường rõ ràng bởi vì hầu hết các hoạt động không lấp đầy toàn bộ màn hình chỉ đơn giản là sử dụng một trong các kiểu hệ thống được cung cấp cho các hộp thoại.
Malcolm

1
Lạ, nhưng trong ứng dụng của tôi hoàn toàn onPause()không được gọi khi hộp thoại được hiển thị. onPause()chỉ được gọi khi tôi nhấn nút home . Sao có thể như thế được?
ateiob

Đây phải là câu trả lời chính xác. Nhân tiện, điều tiền cảnh là một hộp thoại hay hoạt động?
GMsoF

3
@GMsoF Một hoạt động. Đó là điểm chính: không phải mọi hộp thoại thực sự là một hộp thoại. Bạn có thể làm cho một hoạt động trông giống như một hộp thoại, vì vậy nó thực sự nhỏ hơn toàn bộ màn hình.
Malcolm

38

Nếu bạn vẫn có thể thấy bất kỳ phần nào của nó ( Activitysắp tới sẽ không chiếm toàn bộ màn hình, hoặc nó hơi trong suốt), onPause()sẽ được gọi. Nếu bạn không thể thấy bất kỳ phần nào của nó, onStop()sẽ được gọi.

Ví dụ, một hộp thoại ** có thể không bao gồm toàn bộ trước đó Activityvà đây sẽ là thời gian onPause()để được gọi.

** Tôi không đề cập đến Hộp thoại Android ở đây, thay vào đó là một ý tưởng khái niệm về một cái gì đó bật lên và chỉ che khuất một phần của màn hình người dùng. Ghi chú này đã được thêm vào để làm rõ dựa trên nhận xét từ @GMsoF bên dưới


33
KHÔNG. Điều này là sai lệch. Một hộp thoại hiển thị sẽ không gọi onPause () vì hộp thoại sử dụng ngữ cảnh của hoạt động hiện tại, xem xét hoạt động còn sống.
GMsoF

6
@GMsoF Nghe có vẻ như khi tôi nói hộp thoại, bạn nghĩ ý tôi là Dialog, như trong lớp Android. Mặc dù vậy, những gì tôi nhận được là một cái gì đó che khuất một phần đầu tiên Activityđể minh họa ý tưởng rằng tất cả những cái mới Activitykhông cần phải che đậy hoàn toàn trước đó.
nicholas.hauschild

11

Ở trong nền trước có nghĩa là hoạt động có trọng tâm đầu vào. Chẳng hạn, một hoạt động có thể được nhìn thấy nhưng bị che khuất một phần bởi một hộp thoại có tiêu điểm. Trong trường hợp đó, onPause()sẽ được gọi, nhưng không onStop(). Khi hộp thoại biến mất, onResume()phương thức của hoạt động sẽ được gọi (nhưng không onStart()).


5
Điều hộp thoại có thể gây hiểu nhầm. Hãy để một hộp thoại cảnh báo được bật lên từ luồng UI chính của hoạt động này, onPause () sẽ không được gọi trong trường hợp này. Chỉ khi hộp thoại này được bật lên từ Hoạt động khác hoặc Ứng dụng khác.
Sam003

1
@Zhisheng - Tôi đồng ý với nhận xét của bạn. Tôi chỉ diễn giải chủ đề hướng dẫn Activites : " onPause()được gọi khi thiết bị chuyển sang chế độ ngủ hoặc khi hộp thoại xuất hiện" . Như chủ đề này rõ ràng, một hộp thoại không nhất thiết có nghĩa là một hoạt động bị tạm dừng (mặc dù nó sẽ là một hoạt động được hiển thị dưới dạng một hộp thoại ).
Ted Hopp

9

Thực tế , người ta nên xem xét sự khác biệt giữa các nhóm onPause () và trên onPause () + onStop ().

Bất cứ khi nào một số hoạt động mới xảy ra và chiếm một phần không gian của Màn hình. Vì vậy, hoạt động trước đây của bạn vẫn có thể nhìn thấy ở một mức độ nào đó. Trong trường hợp này, hoạt động đang chạy trước đó không được đẩy lên Back Stack. Vì vậy, ở đây chỉ có phương thức onPause () được gọi .

Mặt khác, nếu một số Hoạt động mới xảy ra và chiếm toàn màn hình để hoạt động trước đó của bạn bị biến mất. Trong trường hợp này, hoạt động đang chạy trước đó của bạn được chuyển sang Back Stack. Ở đây, onPause () + onStop () được gọi.

Để tóm tắt-

onPause () - Màn hình được bao phủ một phần bởi hoạt động mới khác. Hoạt động không được chuyển đến Back Stack.

onPause () + onStop () - Màn hình được bao phủ hoàn toàn bởi các hoạt động mới khác. Hoạt động được chuyển đến Back Stack.

Biết thêm về- Back Stack .


0

Nói một cách ngắn gọn:

onStop()của phương thức vòng đời hoạt động trước được gọi khi hoạt động khác được hiển thị. Khi bạn có Đối thoại trên đầu hoạt động, ở đóonPause() được gọi.

Ghi chú : Hoạt động là những thành phần lấp đầy toàn bộ màn hình của bạn.

Lưu ý : Đối thoại không phải là Hoạt động vì chúng không hoàn toàn lấp đầy màn hình.


0

Tôi đã gặp nhiều vấn đề với các phương thức onPause và onStop và do đó tôi sẽ xóa ba tình huống mà tôi gặp phải -
1. Khi bạn nhấp vào nút ứng dụng gần đây, không có phương thức vòng đời nào được gọi nhưng onWindowF FocusChanged (boolean hasF Focus) được gọi với giá trị hasF Focus thông qua là sai. Trong phiên bản Android trước 5, phương thức onPause được sử dụng để được gọi, khi nhấn nút ứng dụng gần đây.

2. Khi một hoạt động bật lên giống như hoạt động xuất hiện trên hoạt động của bạn, như được đề cập bởi Malcolm , nút onPause được gọi. Nếu hoạt động mới chiếm toàn bộ màn hình được gọi, thì onStop được gọi trên hoạt động trước đó. Hộp thoại cấp phép Android cũng khiến hoạt động của bạn gọi onPause.

3.Nếu màn hình hết thời gian cho hoạt động của bạn, thì onPause được gọi. Sau một thời gian nếu bạn không mở màn hình thì onStop sẽ được gọi.

Ngoài ra một điều quan trọng được đề cập bởi ateiob là hoàn thành câu trả lời

Một hoạt động bị tạm dừng hoàn toàn sống động (nó duy trì tất cả thông tin trạng thái và thành viên và vẫn được đính kèm với trình quản lý cửa sổ). Một hoạt động bị dừng cũng giữ lại tất cả thông tin trạng thái và thành viên, nhưng không còn được gắn vào trình quản lý cửa sổ


Hy vọng nó giúp.


0

Bất cứ khi nào HOẠT ĐỘNG mới bắt đầu hoạt động trước đó onPause sẽ được gọi một cách thách thức trong mọi trường hợp.

thực tế sẽ có hai trường hợp:

1- một phần của hoạt động trước có thể nhìn thấy hoặc hoạt động mới là minh bạch: chỉ onPause được gọi.

2- Hoạt động trước được bao phủ hoàn toàn bởi hoạt động mới: cả hai onPauseonStop sẽ được gọi là

---- Tốt để nêu một số lưu ý:

CHÚ THÍCH 1: nếu hộp thoại bắt đầu ở trên cùng của một hoạt động KHÔNG onPause hoặconStop sẽ được gọi.

CHÚ THÍCH 2: nếu một Hoạt động có chủ đề được đặt thành hộp thoại, thì hành vi đó sẽ giống như một hoạt động bình thường.

CHÚ THÍCH 3: rõ ràng là hộp thoại hệ thống như hộp thoại cấp phép vì marshmallow sẽ gây ra onPause.


-5

Yeap, tôi cố gắng hiểu và tôi có thể giải thích điều này dưới đây:

Có 2 hoạt động: ActivityA & ActivityB

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

Đây là hoạt động B. Thực hiện theo nhận xét của tôi trong mã

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

Tôi hy vọng điều này rõ ràng


luôn luôn, cố gắng giải thích điều đó có ý nghĩa
Alexander Zaldostanov
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.