Phương thức Activity.finish () đang làm chính xác là gì?


155

Tôi đang phát triển các ứng dụng Android trong một thời gian và đã theo dõi rất nhiều bài đăng về vòng đời hoạt động và vòng đời của ứng dụng.

Tôi biết Activity.finish()phương thức gọi một nơi nào đó trên đường đến Activity.onDestroy()và cũng loại bỏ hoạt động khỏi ngăn xếp và tôi đoán nó bằng cách nào đó chỉ ra hệ điều hành và trình thu gom rác mà anh ta có thể "thực hiện thủ thuật" và giải phóng bộ nhớ khi thấy đó là thời điểm tốt vì thế....

Tôi đã đến bài viết này - Là bỏ một ứng dụng nhăn mặt? và đọc câu trả lời của Mark Murphy.

Nó làm tôi hơi bối rối về chính xác finish()phương pháp thực sự làm gì.

Có cơ hội nào tôi sẽ gọi finish()onDestroy()sẽ không được gọi không?


Câu trả lời:


171

Khi gọi finish()một hoạt động, phương thức onDestroy()được thực thi. Phương pháp này có thể làm những việc như:

  1. Loại bỏ bất kỳ hộp thoại nào mà hoạt động đang quản lý.
  2. Đóng bất kỳ con trỏ mà hoạt động đang quản lý.
  3. Đóng bất kỳ hộp thoại tìm kiếm mở

Ngoài ra, onDestroy()không phải là một kẻ hủy diệt. Nó không thực sự phá hủy đối tượng. Đó chỉ là một phương pháp được gọi dựa trên một trạng thái nhất định. Vì vậy, cá thể của bạn vẫn còn sống và rất tốt * sau khi siêu lớp onDestroy()chạy và trả về .ndroid giữ các tiến trình xung quanh trong trường hợp người dùng muốn khởi động lại ứng dụng, điều này làm cho giai đoạn khởi động nhanh hơn. Quá trình sẽ không làm bất cứ điều gì và nếu cần phải thu hồi bộ nhớ, quá trình sẽ bị giết


5
vì vậy phương thức finish () chỉ kích hoạt lệnh gọi tới onDestroy () và đó là nó?
Tal Kanel

9
Có, nếu bạn quay lại Activity onCreate () sẽ được gọi.
Luis Pena

9
Kết thúc () cũng gọi onPause () và onStop ()?
sr09

36
Tôi đã thử nghiệm lại và thấy rằng onPause (), onStop () và onDestroy () sẽ được gọi theo thứ tự sau khi bạn gọi kết thúc ().
Sam003

5
@Laurent onPause () và onStop () không phải lúc nào cũng được gọi. Xem quan sát của tôi trong câu trả lời dưới đây
Prakash

77

2 xu của tôi trên @K_Anas trả lời. Tôi đã thực hiện một thử nghiệm đơn giản trên phương thức finish (). Liệt kê các phương thức gọi lại quan trọng trong vòng đời hoạt động

  1. Gọi kết thúc () trong onCreate (): onCreate () -> onDestroy ()
  2. Gọi kết thúc () trong onStart (): onCreate () -> onStart () -> onStop () -> onDestroy ()
  3. Gọi kết thúc () trong onResume (): onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Điều tôi muốn nói là các đối tác của các phương thức cùng với bất kỳ phương thức nào ở giữa được gọi khi kết thúc () được thực thi.

ví dụ:

 onCreate() counter part is onDestroy()
 onStart() counter part is onStop()
 onPause() counter part is onResume()

Điều gì nếu bạn gọi kết thúc bên trong onPause? nó sẽ gọi onStop> onDestroy?
rmpt

Bảng đó thực sự hữu ích và mô tả (bạn phải cuộn xuống một chút) developer.android.com/reference/android/app/iêu
winklerrr

Bản thân tôi đã xác minh rằng câu trả lời này là chính xác.
Saletanth Karumanaghat

33

Cũng lưu ý nếu bạn gọi kết thúc () sau khi có ý định, bạn không thể quay lại hoạt động trước đó bằng nút "quay lại"

startActivity(intent);
finish();

Đây chính xác là thông tin tôi cần, vì tôi có một hoạt động chỉ kết nối với google drive, sau đó nó sẽ kiểm tra và chuyển sang hoạt động chính (hoặc hoạt động Cài đặt nếu có lỗi), vì vậy người dùng không nên Sẽ không thể quay lại.
Francesco Marchetti-Stasi

1
@Francesco Marchetti-Stasi Trong trường hợp của bạn, sẽ tốt hơn là ghi đè onBackPression () và không gọi super.onBackPression () trong đó nếu người dùng không nên quay lại.
Paul

13

onDestroy()có nghĩa là để dọn dẹp lần cuối - giải phóng các tài nguyên mà bạn có thể tự mình làm, đóng các kết nối mở, độc giả, nhà văn, v.v. Nếu bạn không ghi đè lên nó, hệ thống sẽ làm những gì nó phải làm.

mặt khác, finish()chỉ cần cho hệ thống biết rằng lập trình viên muốn dòng điện Activitykết thúc. Và do đó, nó gọi lênonDestroy() sau đó.

Một vài điều cần lưu ý:

không cần thiết chỉ có một cuộc gọi để finish()kích hoạt một cuộc gọi đến onDestroy(). Như chúng ta đã biết, hệ thống Android có thể tự do tiêu diệt các hoạt động nếu cảm thấy rằng có những tài nguyên cần thiết cho dòng điện Activitycần được giải phóng.


1
bạn đã viết xong () cho hệ thống biết hoạt động cần kết thúc. vì vậy nó giống như nói "do x = bảo hệ thống làm x". Điều thứ hai: từ câu trả lời của bạn có vẻ như có một cách tôi sẽ gọi kết thúc () và hệ thống sẽ quyết định không gọi onDestroy ()? có thể không
Tal Kanel

Bạn đã có phần đầu tiên đúng. Gọi finish()là nói với hệ thống để kết thúc Activity. phần "x" trong câu lệnh do của bạn là "kết thúc (hủy) Activity". Phần thứ hai là sai. Thật ra, tôi đã bỏ lỡ một từ ở đó. Tôi đã chỉnh sửa câu trả lời. onDestroy()không chỉ được kích hoạt bởi finish(), hệ thống cũng có thể tự gọi nó.
Kazekage Gaara

1
Tôi vừa đọc phần bổ sung của bạn vào câu trả lời. bây giờ tôi đã bình chọn câu trả lời vì tôi thấy lời giải thích của bạn thú vị, nhưng tôi muốn xem liệu người khác có nói gì khác không trước khi đánh dấu nó là "câu trả lời". cảm ơn ngay bây giờ :)
Tal Kanel

Vậy sau khi kết thúc (), tất cả các biến trong hoạt động này sẽ bị hủy, phải không? Khi tôi trở lại hoạt động này một lần nữa, chúng sẽ được khai báo lại hoặc khởi tạo, phải không?
Đánh bạc Sibbs

3
Lưu ý: nếu hệ thống giết quá trình, onDestroy có thể không được gọi. developer.android.com/reference/android/app/NH
Kevin Lee

9

Phương thức kết thúc () sẽ phá hủy hoạt động hiện tại. Bạn có thể sử dụng phương pháp này trong các trường hợp khi bạn không muốn hoạt động này tải lại nhiều lần khi người dùng nhấn nút quay lại. Về cơ bản, nó xóa hoạt động từ ngăn xếp hiện tại.


8

Ngoài câu trả lời @rommex ở trên, tôi cũng nhận thấy rằng finish()việc xếp hàng hủy hoạt động và nó phụ thuộc vào mức độ ưu tiên của Hoạt động.

Nếu tôi gọi finish()sau onPause(), tôi thấy onStop(), và onDestroy()ngay lập tức gọi.

Nếu tôi gọi finish()sau onStop(), tôi sẽ không thấy onDestroy()đến 5 phút sau.

Từ quan sát của tôi, có vẻ như kết thúc được xếp hàng và khi tôi nhìn vào adb shell dumpsys activity activitiesnó được đặt finishing=true, nhưng vì nó không còn ở phía trước, nên nó không được ưu tiên để phá hủy.

Tóm lại, onDestroy()không bao giờ được đảm bảo để được gọi, nhưng ngay cả trong trường hợp nó được gọi, nó có thể bị trì hoãn.


5

Nhiều câu trả lời và ghi chú khác nhau cho rằng finish () có thể bỏ qua onPause () và onStop () và trực tiếp thực thi onDestroy (). Công bằng mà nói, tài liệu Android về điều này ( http://developer.android.com/reference/android/app/Activity.html ) lưu ý "Hoạt động đang hoàn thiện hoặc bị hệ thống phá hủy" khá mơ hồ nhưng có thể gợi ý rằng finish () có thể nhảy tới onDestroy ().

JavaDoc on finish () cũng gây thất vọng tương tự ( http://developer.android.com/reference/android/app/Activity.html#finish () ) và không thực sự lưu ý phương thức nào được gọi để hoàn thành ().

Vì vậy, tôi đã viết ứng dụng nhỏ này bên dưới để ghi lại từng trạng thái khi nhập cảnh. Nó bao gồm một nút gọi kết thúc () - vì vậy bạn có thể thấy nhật ký của các phương thức được kích hoạt. Thử nghiệm này sẽ gợi ý rằng finish () thực sự cũng gọi onPause () và onStop (). Đây là đầu ra tôi nhận được:

2170-2170/? D/LIFECYCLE_DEMO INSIDE: onCreate
2170-2170/? D/LIFECYCLE_DEMO INSIDE: onStart
2170-2170/? D/LIFECYCLE_DEMO INSIDE: onResume
2170-2170/? D/LIFECYCLE_DEMO User just clicked button to initiate finish() 
2170-2170/? D/LIFECYCLE_DEMO INSIDE: onPause
2170-2170/? D/LIFECYCLE_DEMO INSIDE: onStop 
2170-2170/? D/LIFECYCLE_DEMO INSIDE: onDestroy

package com.mvvg.apps.lifecycle;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;

public class AndroidLifecycle extends Activity {

    private static final String TAG = "LIFECYCLE_DEMO";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "INSIDE: onCreate");
        setContentView(R.layout.activity_main);
        LinearLayout layout = (LinearLayout) findViewById(R.id.myId);
        Button button = new Button(this);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View view) {
                Toast.makeText(AndroidLifecycle.this, "Initiating finish()",
                        Toast.LENGTH_SHORT).show();
                Log.d(TAG, "User just clicked button to initiate finish()");
                finish();
            }

        });

        layout.addView(button);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "INSIDE: onStart");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "INSIDE: onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "INSIDE: onDestroy");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "INSIDE: onPause");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "INSIDE: onResume");
    }

}

3

@ user3282164 Theo vòng đời Hoạt động , nó sẽ đi qua onPause()-> onStop()-> onDestroy()khi gọifinish() .

Sơ đồ không hiển thị bất kỳ đường thẳng nào từ [Chạy hoạt động] đến [ onDestroy()] do hệ thống gây ra.

onStop () doc nói " Lưu ý rằng phương thức này có thể không bao giờ được gọi, trong các tình huống bộ nhớ thấp trong đó hệ thống không có đủ bộ nhớ để duy trì quá trình hoạt động của bạn sau khi phương thức onPause () của nó được gọi. "



2

Nghiên cứu của tôi cho thấy finish()phương pháp thực sự đặt một số hoạt động hủy trong hàng đợi, nhưng Hoạt động không bị hủy ngay lập tức. Sự hủy diệt được lên kế hoạch mặc dù.

Ví dụ: nếu bạn đặt finish()trong onActivityResult()cuộc gọi lại, trong khi onResume()vẫn chưa chạy, thì đầu tiên onResume()sẽ được thực thi và chỉ sau đó onStop()onDestroy() được gọi.

LƯU Ý: onDestroy()có thể không được gọi ở tất cả, như đã nêu trong tài liệu .


2

kết thúc cuộc gọi trong onCreate () sẽ không gọi trực tiếp onDestroy () như @prakash nói. Cácfinish() hoạt động thậm chí sẽ không bắt đầu cho đến khi bạn trở về điều khiển Android.

Gọi kết thúc () trong onCreate () : onCreate () -> onStart () -> onResume () . Nếu người dùng thoát, ứng dụng sẽ gọi -> onPause () -> onStop () -> onDestroy ()

Gọi kết thúc () trong onStart () : onCreate () -> onStart () -> onStop () -> onDestroy ()

Gọi kết thúc () trong onResume () : onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Để tham khảo thêm, hãy xem liên tục này sau khi kết thúc & về kết thúc ()


0

Dường như câu trả lời đúng duy nhất ở đây cho đến nay đã được đưa ra bởi romnex: "onDestroy () có thể không được gọi ở tất cả". Mặc dù trong thực tế, trong hầu hết các trường hợp, sẽ không có gì đảm bảo: Tài liệu về kết thúc () chỉ hứa rằng kết quả của hoạt động được truyền lại cho người gọi, nhưng không có gì hơn. Hơn nữa, tài liệu về vòng đời làm rõ rằng hoạt động có thể bị HĐH phá hủy ngay khi onStop () kết thúc (hoặc thậm chí sớm hơn trên các thiết bị cũ), mặc dù không thể và do đó hiếm khi quan sát trong một thử nghiệm đơn giản, có thể có nghĩa là hoạt động đó có thể bị giết trong khi hoặc thậm chí trước khi onDestroy () được thực thi.

Vì vậy, nếu bạn muốn đảm bảo một số công việc được thực hiện khi bạn gọi kết thúc (), bạn không thể đặt nó vào onDestroy (), nhưng sẽ cần thực hiện ở cùng một nơi mà bạn gọi kết thúc (), ngay trước khi thực sự gọi nó.


-4

finish () chỉ gửi lại cho hoạt động trước đó trong Android hoặc có thể bạn có thể nói rằng nó sẽ lùi một bước trong ứng dụng

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.