Xóa một hoạt động khỏi ngăn xếp lịch sử


382

Ứng dụng của tôi hiển thị hoạt động đăng ký vào lần đầu tiên người dùng chạy ứng dụng, trông giống như:

  1. ActivitySplashScreen (chào mừng bạn đến với trò chơi, đăng ký tài khoản?)
  2. ActivitySplashScreenSignUp (tuyệt vời, điền thông tin này)
  3. ActivityGameMain (màn hình trò chơi chính)

vì vậy các hoạt động khởi chạy lẫn nhau theo đúng thứ tự đó, khi người dùng nhấp qua một nút trên mỗi màn hình.

Khi người dùng chuyển từ hoạt động # 2 sang # 3, có thể xóa hoàn toàn # 1 và # 2 khỏi ngăn xếp lịch sử không? Tôi muốn nó để nếu người dùng ở số 3 và nhấn nút quay lại, họ chỉ cần vào màn hình chính, thay vì quay lại màn hình giật gân.

Tôi nghĩ rằng tôi có thể thực hiện điều này với các nhiệm vụ (ví dụ: bắt đầu một nhiệm vụ mới trên # 3) nhưng muốn xem liệu có phương pháp đơn giản hơn không,

Cảm ơn


Sau khi ở trong màn hình chính, khi người dùng tiếp tục ứng dụng của bạn, nó sẽ đưa anh ta đến ActivitySplashScreen hoặc ActivityGameMain?
Tamil

Câu trả lời:


632

Bạn có thể đạt được điều này bằng cách thiết lập android:noHistory thuộc tính để "true"trong liên quan <activity>mục trong của bạn AndroidManifest.xmltập tin. Ví dụ:

<activity
    android:name=".AnyActivity"
    android:noHistory="true" />

12
Đây là cách tốt nhất để làm điều đó.
shkschneider

22
Tương đương bạn có thể sử dụng FLAG_ACTIVITY_NO_HISTORY.
Timmmm

34
Làm thế nào tôi có thể đạt được điều này từ mã? Bởi vì tôi không muốn làm điều này mọi lúc. Tôi muốn xóa một hoạt động nhất định khỏi lịch sử chỉ trong một số điều kiện.
Namratha

8
Chỉ cần lưu ý rằng việc sử dụng thuộc tính noHistory sẽ khiến hoạt động đó kết thúc, điều này có thể gây ra hành vi không mong muốn với đăng nhập G + chẳng hạn. Xem: stackoverflow.com/questions/20383878/ Từ Tôi đã gặp tôi một lúc để tìm lỗi này khi ứng dụng của tôi liên tục gặp sự cố mà không có bất kỳ dấu vết nào.
Acapulco

13
Rất khó để sao chép cờ cần thiết vì nó là một liên kết, vì vậy ở đây có thể dễ dàng sao chép. android:noHistory="true"
MirroredFate

137

Bạn có thể sử dụng chuyển tiếp để xóa hoạt động trước đó khỏi ngăn xếp hoạt động trong khi khởi chạy hoạt động tiếp theo. Có một ví dụ về điều này trong APIDemos , nhưng về cơ bản, tất cả những gì bạn đang làm là gọi finish()ngay sau khi gọi startActivity().


1
Xin chào Daniel, tôi đã đọc qua ví dụ, nhưng điều đó sẽ chỉ xóa ngăn xếp lịch sử bằng 1 hoạt động, phải không? Nếu ngăn xếp của tôi trông giống A, B và tôi khởi chạy C, tôi muốn C là gốc mới và hoàn toàn xóa A và B. Trong ví dụ sdk, việc gọi kết thúc () từ B sẽ để lại cho tôi một ngăn xếp A , C, phải không? Cảm ơn.
Đánh dấu

1
Bạn có thể xóa A khi bạn khởi chạy B và xóa B khi bạn khởi chạy C; tuy nhiên, tôi cho rằng sau đó bạn sẽ không thể rút lui từ B sang A nếu đó là điều bạn mong muốn. Tôi sẽ phải suy nghĩ về vấn đề này nhiều hơn nếu đó là một vấn đề.
Dan Lew

3
Đánh dấu, để đạt được những gì bạn muốn, bạn phải sử dụng cờ: FLAG_ACTIVITY_CLEAR_TOP. Tôi hy vọng nó sẽ giúp.
Francisco Junior

3
FLAG_ACTIVITY_CLEAR_TOPsẽ không hoạt động vì C chưa có trong ngăn xếp phía sau.
Timmmm

1
@DanielLew Có rất nhiều ví dụ trong APIDemos. Bạn muốn có tên của ví dụ được đề xuất?
Stephane

52

46
Lưu ý rằng điều này không đặt lịch sử cho hoạt động bạn đang khởi chạy. Để không có lịch sử cho hoạt động bạn khởi chạy, tôi chỉ cần đặt nó android:noHistory="true"trong tệp kê khai.
georgiecasey

1
Điều này làm việc tốt. Sử dụng intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)để đặt cờ này.
vovahost

1
@georgiecasey điều này hữu ích khi đôi khi bạn muốn giữ nó trong lịch sử và đôi khi bạn không muốn nó trong lịch sử.
Vihaan Verma

24

Đây có thể không phải là cách lý tưởng để làm điều đó. Nếu ai đó có cách tốt hơn, tôi sẽ mong muốn thực hiện nó. Đây là cách tôi hoàn thành nhiệm vụ cụ thể này với sdk tiền phiên bản-11.

trong mỗi lớp bạn muốn đi khi hết giờ, bạn cần làm điều này:

    ... interesting code stuff ...
    Intent i = new Intent(MyActivityThatNeedsToGo.this, NextActivity.class);
    startActivityForResult(i, 0);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == R.string.unwind_stack_result_id) {
        this.setResult(R.string.unwind_stack_result_id);
        this.finish();
    }
}

sau đó, cái cần thiết để tắt chuỗi pops từ ngăn xếp chỉ cần gọi cái này khi bạn muốn khởi tạo nó:

NextActivity.this.setResult(R.string.unwind_stack_result_id);
NextActivity.this.finish();

Sau đó, các hoạt động không có trong ngăn xếp!
Hãy nhớ mọi người, rằng bạn có thể bắt đầu một hoạt động, và sau đó bắt đầu dọn dẹp đằng sau nó, việc thực thi không theo một chuỗi (ui) nào.


Trong trường hợp bất cứ ai gặp phải điều này sau đó, tôi nghĩ nó có thể chứng minh là rất quan trọng để biết, nếu bạn xoay màn hình, android sẽ giúp khởi động lại ứng dụng của bạn cho bạn khi bạn tắt hoạt động cuối cùng của ngăn xếp. Chỉ cần nhận thức được điều này!
Travis

Đây là một câu trả lời tốt nếu bạn chỉ muốn xóa một hoạt động khỏi ngăn xếp một cách có điều kiện tùy thuộc vào những gì người dùng làm trong hoạt động tiếp theo +1
theMothaShip

23

Một cách hoạt động trước API 11 là bắt ActivityGameMainđầu trước, sau đó trong onCreateHoạt động đó bắt đầu ActivitySplashScreenhoạt động của bạn . Các ActivityGameMainsẽ không xuất hiện khi bạn gọi startActivity quá sớm cho giật gân.

Sau đó, bạn có thể xóa ngăn xếp khi bắt đầu ActivityGameMainbằng cách đặt các cờ này trên Ý định:

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

Bạn cũng phải thêm phần này vào ActivitySplashScreen:

@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

Vì vậy, nhấn vào hoạt động đó không quay trở lại của bạn ActivityGameMain.

Tôi giả sử bạn không muốn màn hình giật gân quay trở lại, để đạt được điều này, tôi khuyên bạn nên đặt màn hình noHistoryvào trong AndroidManifest.xml. Sau đó, đặt goBackPressedmã trong ActivitySplashScreenSignUplớp của bạn thay thế.

Tuy nhiên tôi đã tìm thấy một vài cách để phá vỡ điều này. Bắt đầu một ứng dụng khác từ một thông báo trong khi ActivitySplashScreenSignUpđược hiển thị và lịch sử trở lại không được đặt lại.

Cách thực sự duy nhất xoay quanh vấn đề này là trong API 11:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

20

Tôi sử dụng cách này.

Intent i = new Intent(MyOldActivity.this, MyNewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);

Cảm ơn. Tôi thấy điều này hữu ích trong trường hợp có nút Home trong menu của tôi và tôi không muốn các hoạt động xếp chồng xuất hiện khi người dùng nhấp vào nhà từ đó.
ghitesh

8

Tôi biết tôi đã trễ về vấn đề này (đã hai năm kể từ khi câu hỏi được hỏi) nhưng tôi đã hoàn thành việc này bằng cách chặn nút nhấn trở lại. Thay vì kiểm tra các hoạt động cụ thể, tôi chỉ nhìn vào số đếm và nếu nó nhỏ hơn 3, nó chỉ cần gửi ứng dụng ra phía sau (tạm dừng ứng dụng và đưa người dùng trở lại bất cứ thứ gì đang chạy trước khi khởi chạy). Tôi kiểm tra ít hơn ba vì tôi chỉ có một màn hình giới thiệu. Ngoài ra, tôi kiểm tra số lượng vì ứng dụng của tôi cho phép người dùng điều hướng trở lại màn hình chính thông qua menu, vì vậy điều này cho phép họ sao lưu qua các màn hình khác như bình thường nếu có các hoạt động khác ngoài màn hình giới thiệu trên ngăn xếp.

//We want the home screen to behave like the bottom of the activity stack so we do not return to the initial screen
//unless the application has been killed. Users can toggle the session mode with a menu item at all other times.
@Override
public void onBackPressed() {
    //Check the activity stack and see if it's more than two deep (initial screen and home screen)
    //If it's more than two deep, then let the app proccess the press
    ActivityManager am = (ActivityManager)this.getSystemService(Activity.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(3); //3 because we have to give it something. This is an arbitrary number
    int activityCount = tasks.get(0).numActivities;

    if (activityCount < 3)
    {
        moveTaskToBack(true);
    }
    else
    {
        super.onBackPressed();
    }
}

7

Trong bảng kê khai bạn có thể thêm:

android:noHistory="true"

<activity
android:name=".ActivityName"
android:noHistory="true" />

Bạn cũng có thể gọi

finish()

ngay sau khi gọi startActivity (..)


2
Tốt hơn để sử dụng cờ hoạt động hơn là đặt mọi thứ trong bảng kê khai.
Trevor Hart

6

Chỉ cần đặt noHistory="true"trong tệp Manifest . Nó làm cho hoạt động được loại bỏ từ backstack.


4

Thật điên rồ khi không ai nhắc đến giải pháp tao nhã này. Đây phải là câu trả lời được chấp nhận.

SplashActivity -> AuthActivity -> DashActivity

if (!sessionManager.isLoggedIn()) {
    Intent intent = new Intent(context, AuthActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
    context.startActivity(intent);
    finish();
} else {
   Intent intent = new Intent(context, DashActivity.class);
   context.startActivity(intent);
    finish();
}

Chìa khóa ở đây là sử dụng intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); cho trung gian Activity. Khi liên kết giữa đó bị hỏng, ý DashActivitychí đầu tiên và cuối cùng trong ngăn xếp.

android:noHistory="true"là một giải pháp tồi, vì nó gây ra vấn đề khi dựa vào Activitynhư một cuộc gọi lại, vd onActivityResult. Đây là giải pháp được đề nghị và nên được chấp nhận.


1
Lá cờ đó nghe có vẻ quá tốt là đúng. FLAG_ACTIVITY_NO_HISTORY hoạt động độc đáo và như mọi người mong đợi cho đến khi người ta đặt ứng dụng làm nền và sau đó lại tiếp tục trong khi có hoạt động với cờ trên đầu ngăn xếp. Khi đi đến nền, các hoạt động bị phá hủy. Khi trở lại ứng dụng, người ta sẽ thấy hoạt động trước đó từ ngăn xếp. Tôi chắc chắn không muốn hành vi như vậy.
NeverwinterMoon

4

Quá muộn nhưng hy vọng nó sẽ giúp. Hầu hết các câu trả lời không chỉ đúng hướng. Có hai lá cờ đơn giản cho điều đó.

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

Từ tài liệu Android:

chung kết tĩnh int FLAG_ACTIVITY_CLEAR_TASK Đã thêm vào API cấp 11

If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the

hoạt động được 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 cùng với FLAG_ACTIVITY_NEW_TASK.


1

Chỉ cần gọi this.finish () trước startActivity (ý định) như thế này-

       Intent intent = new Intent(ActivityOne.this, ActivityTwo.class);
        this.finish();
        startActivity(intent);

người dùng có lỗi về "này", nên đổi nó thành "ActivityOne.this"
ninbit 17/8/18

1

Xóa một hoạt động khỏi Lịch sử được thực hiện bằng cách đặt cờ trước hoạt động bạn không muốn

A-> B-> C-> D

Giả sử A, B, C và D là 4 Hoạt động nếu bạn muốn xóa B và C sau đó đặt cờ

intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

Trong hoạt động A và B

Đây là bit mã

Intent intent = new Intent(this,Activity_B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);

0
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            super.finishAndRemoveTask();
        }
        else {
            super.finish();
        }

-7

Thử cái này:

intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)

Đó là API cấp 1, kiểm tra liên kết .


2
Điều này là để làm gì? Chắc chắn không giải quyết được vấn đề trong câu hỏi.
Rodrigo-silveira

Bạn có chắc là bạn không cố ý Intent.FLAG_ACTIVITY_NO_HISTORY?
Riot đi lang thang
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.