Android: Xóa hoạt động ngăn xếp


132

Tôi đang có một vài hoạt động trong ứng dụng của mình. và dòng chảy rất phức tạp. Khi tôi nhấp vào ứng dụng Đăng xuất điều hướng để đăng nhập Màn hình và từ đó người dùng có thể thoát bằng nút hủy (gọi system.exit(0))

Khi tôi thoát hoặc quay lại nút, hệ thống sẽ gọi một hoạt động từ ngăn xếp :( làm cách nào tôi có thể xóa tất cả các hoạt động trong ngăn xếp khi tôi đến màn hình Đăng nhập? Cuộc gọi finish()không thực tế vì có quá nhiều hoạt động và một số hoạt động không nên đóng khi họ đang hoạt động như hoạt động gọi máy ảnh bản địa.

validateuser logoutuser = new validateuser();
logoutuser.logOut();
Intent loginscreen = new Intent(homepage.this, Login2.class);
(homepage.this).finish();
loginscreen.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(loginscreen);


Bản sao có thể có của Android: Xóa ngăn xếp phía sau
Mehdi Dehghani

Câu trả lời:


339

Hầu hết các bạn đều sai. Nếu bạn muốn đóng ngăn xếp hoạt động hiện tại bất kể có gì trong đó và tạo root mới, bộ cờ chính xác là như sau:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Từ tài liệu :

public static final int FLAG_ACTIVITY_CLEAR_TASK
Đã thêm trong API cấp 11

Nếu được đặt trong Ý định được chuyển đến Context.startActivity(), cờ này sẽ khiến mọi tác vụ hiện có liên quan đến hoạt động sẽ bị xóa trước khi hoạt động được bắt đầu. Nghĩa là, hoạt động trở thành gốc mới của một nhiệm vụ trống rỗng khác và mọi hoạt động cũ đã kết thúc. Điều này chỉ có thể được sử dụng kết hợp với FLAG_ACTIVITY_NEW_TASK.


Làm việc hoàn hảo. Cảm ơn. Điều kỳ lạ là không đưa ra lỗi với minSDK = 9.
Mahm00d

Thành thật mà nói, tôi không bao giờ sử dụng chức năng này, hồi sinh sau sự cố, v.v., và tập trung vào khắc phục các sự cố gây ra sự cố)
Cynichniy Bandera

Chức năng tương tự cũng cung cấp IntentCompat.makeRestartActivityTasktừ thư viện hỗ trợ.
sealskej

Chỉ thêm hai cờ đó để lại dấu vết ngăn xếp hoạt động phía sau (bắt đầu trên đầu cờ trước), sau đó thêm Intent.FLAG_ACTIVITY_CLEAR_TOP, đơn giản chỉ cần khởi động lại ứng dụng và sau đó thoát hoàn toàn. Tôi đã không thêm bất kỳ cờ nào cho các hoạt động rõ ràng tho. Điều gì có thể là vấn đề?
Farid

1
Một trong những khởi đầu tốt nhất: "Hầu hết các bạn đều sai."
niết bàn

31

Khi bạn gọi startActivitycho hoạt động cuối cùng, bạn luôn có thể sử dụng

Intent.FLAG_ACTIVITY_CLEAR_TOP

như một lá cờ trên ý định đó.

Tìm hiểu thêm về cờ ở đây .


Điều đó cũng không giúp được gì. Tôi vừa đưa ra một hoạt động dat không kết thúc bằng finish (); :(
Jay Mayu

Tôi đoán FLAG_ACTIVITY_CLEAR_TOP xóa các hoạt động trên đầu trang. Vấn đề của tôi là các hoạt động ở phía dưới :(
Jay Mayu

Tôi đoán nó phụ thuộc vào cách dòng chảy thực sự. Bạn nên đọc thêm về nó ở đây: developer.android.com/reference/android/content/...developer.android.com/guide/topics/fundamentals/...
David Olsson

7
Cảm ơn đã hiển thị tài nguyên chính xác. lỗi tôi đã làm là đóng hoạt động Đăng nhập. Tôi không nên đóng nó. Khi các hoạt động được tải đầu tiên. vì vậy khi tôi gọi lại bằng cờ Clear_top, hoạt động đăng nhập sẽ xóa tất cả các hoạt động trên đầu trang. vì đăng nhập là hoạt động đầu tiên, nó xóa tất cả các hoạt động bắt đầu sau đó. vì vậy bingo nó đã hoạt động :)
Jay Mayu

13
Từ tài liệu, FLAG_ACTIVITY_CLEAR_TOP chỉ xóa ngăn xếp nếu hoạt động cụ thể "đã chạy trong tác vụ hiện tại"
AlikElzin-kilaka

16

Đây là một phương thức trợ giúp đơn giản để bắt đầu một hoạt động mới là hoạt động hàng đầu mới hoạt động từ API cấp 4 cho đến phiên bản hiện tại 17:

static void startNewMainActivity(Activity currentActivity, Class<? extends Activity> newTopActivityClass) {
    Intent intent = new Intent(currentActivity, newTopActivityClass);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        intent.addFlags(0x8000); // equal to Intent.FLAG_ACTIVITY_CLEAR_TASK which is only available from API level 11
    currentActivity.startActivity(intent);
}

gọi nó như thế này từ hoạt động hiện tại của bạn:

startNewMainActivity(this, MainActivity.class);

1
Không phải lúc nào bạn cũng chỉ sử dụng aim.addFlags (0x8000); và đơn giản hóa điều đó?
Thưởng thức

Vì lá cờ này lần đầu tiên được giới thiệu trong Honeycomb, tôi không biết nó có thể có ý nghĩa gì đối với các phiên bản trước. Vì vậy, đây là tôi là preaucios. Nhưng tôi đoán việc loại bỏ các điều kiện không nên là một vấn đề.
whlk

1
bạn muốn thêm cờ đó khi cấp API <11 thì bạn cần phải làm Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMBkhác intent.addFlags(0x8000);sẽ không bao giờ thêm
Mũ rơm

Tôi đang có người dùng đi qua nhiều hoạt động lần lượt thông qua ý định. Tôi có cần phải làm bất cứ điều gì để đảm bảo ứng dụng không bị sập với quá nhiều hoạt động trên ngăn xếp không? Cảm ơn!
Ruchir Baronia

9

Xóa hoạt động Backstate bằng mã dưới đây:

Intent intent = new Intent(Your_Current_Activity.this, Your_Destination_Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK |Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Làm xong


Tôi đang có người dùng đi qua nhiều hoạt động lần lượt thông qua ý định. Tôi có cần phải làm bất cứ điều gì để đảm bảo ứng dụng không bị sập với quá nhiều hoạt động trên ngăn xếp không? Cảm ơn!
Ruchir Baronia

@RuchirBaronia, Nếu bạn đi A -> B -> C -> D -> E -> F -> G -> H, bây giờ H -> Tôi viết mã của tôi hơn tôi sẽ là Hoạt động cuối cùng sau đó bạn nhấn nút Quay lại Ứng dụng sẽ đóng cửa vì ứng dụng không có hoạt động hậu trường, hy vọng điều này sẽ giúp bạn.
Hiren Patel

Tôi có cần phải làm điều đó mặc dù? Điều gì sẽ xảy ra nếu tôi không bao giờ dọn dẹp ngăn xếp hoạt động?
Ruchir Baronia

@RuchirBaronia, Backpress: H -> G -> F -> E -> D -> C -> B -> A
Hiren Patel

Nhưng đôi khi nó hiển thị màn hình trắng trong khi gọi hoạt động mới. Hồ để giải quyết chuyện này?
Sagar

4

Trong trường hợp của tôi, LoginActivity cũng bị đóng. Kết quả là

Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK

đã không giúp được gì.

Tuy nhiên, cài đặt

Intent.FLAG_ACTIVITY_NEW_TASK

đã giúp tôi


Tôi đang có người dùng đi qua nhiều hoạt động lần lượt thông qua ý định. Tôi có cần phải làm bất cứ điều gì để đảm bảo ứng dụng không bị sập với quá nhiều hoạt động trên ngăn xếp không? Cảm ơn!
Ruchir Baronia

3
Intent intent = new Intent(LoginActivity.this, Home.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  //It is use to finish current activity
startActivity(intent);
this.finish();

1
Tại sao bạn đang sử dụng cả hai this.finish()setFlags()cũng để xóa hoạt động hiện tại?
Sagar

3

Tôi lưu ý rằng bạn đã yêu cầu một giải pháp không dựa vào finish(), nhưng tôi tự hỏi liệu điều này có thể giúp ích gì không.

Tôi đã theo dõi xem một cờ thoát được đưa lên với một biến lớp tĩnh, tồn tại trong toàn bộ tuổi thọ của ứng dụng. Trong mỗi hoạt động liên quanonResume() , sử dụng

@Override
public void onResume() {
    super.onResume();
    if (ExitHelper.isExitFlagRaised) {
        this.finish();
    }
}

Lớp ExitHelper

public class ExitHelper {
    public static boolean isExitFlagRaised = false;
}

Giả sử trong mainActivity, người dùng nhấn nút để thoát - bạn có thể đặt ExitHelper.isExitFlagRaised = true;và sau đó finish(). Sau đó, các hoạt động liên quan khác được nối lại tự động cũng sẽ kết thúc.


Điều gì sẽ xảy ra nếu tôi sử dụng mã trong MainActivity onresume () sau đó quay lại hoạt động chính từ hoạt động thứ 2 onbackpress
Mithu

3

Quyết định này hoạt động tốt:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Nhưng hoạt động mới ra mắt lâu và bạn thấy màn hình trắng một thời gian. Nếu điều này là quan trọng thì hãy sử dụng cách giải quyết này:

public class BaseActivity extends AppCompatActivity {

    private static final String ACTION_FINISH = "action_finish";

    private BroadcastReceiver finisBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        registerReceiver(finisBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                finish();
            }
        }, new IntentFilter(ACTION_FINISH));
    }

    public void clearBackStack() {
        sendBroadcast(new Intent(ACTION_FINISH));
    }

    @Override
    protected void onDestroy() {
        unregisterReceiver(finisBroadcastReceiver);
        super.onDestroy();
    }
}

Cách sử dụng:

public class ActivityA extends BaseActivity {

    // Click any button
    public void startActivityB() {
        startActivity(new Intent(this, ActivityB.class));
        clearBackStack();
    }
}

Nhược điểm: tất cả các hoạt động phải được đóng trên ngăn xếp phải mở rộng BaseActivity


2

Đối với Nhà phát triển Xamarin, bạn có thể sử dụng:

intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);

1

Sử dụng Kotlin:

Bạn có thể đặt cờ trực tiếp bằng phương thức setter. Trong Kotlin orlà sự thay thế cho Java bitwise hoặc |.

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

Nếu bạn có kế hoạch sử dụng điều này thường xuyên, hãy tạo chức năng mở rộng Ý định

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

Sau đó, bạn có thể gọi trực tiếp chức năng này trước khi bắt đầu ý định

intent.clearStack()
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.