การลบกิจกรรมออกจากสแต็กประวัติ


382

แอพของฉันแสดงกิจกรรมการสมัครเป็นครั้งแรกที่ผู้ใช้รันแอพดูเหมือนว่า:

  1. ActivitySplashScreen (ยินดีต้อนรับสู่เกมสมัครใช้งานบัญชี?)
  2. ActivitySplashScreenSignUp (ดีมากกรอกข้อมูลนี้)
  3. ActivityGameMain (หน้าจอเกมหลัก)

ดังนั้นกิจกรรมที่เปิดตัวกันในลำดับที่เมื่อผู้ใช้คลิกผ่านปุ่มในแต่ละหน้าจอ

เมื่อผู้ใช้เปลี่ยนจากกิจกรรม # 2 ถึง # 3 เป็นไปได้ไหมที่จะลบ # 1 และ # 2 ออกจากสแต็กประวัติทั้งหมด? ฉันต้องการให้ผู้ใช้อยู่ที่ # 3 และกดปุ่มย้อนกลับพวกเขาเพียงไปที่หน้าจอหลักแทนที่จะกลับไปที่หน้าจอเริ่มต้น

ฉันคิดว่าฉันสามารถทำสิ่งนี้ได้ด้วยงาน (เช่นเริ่มงานใหม่ใน # 3) แต่ต้องการดูว่ามีวิธีที่ง่ายกว่านี้ไหม

ขอบคุณ


หลังจากอยู่ในหน้าจอหลักเมื่อผู้ใช้ดำเนินการต่อแอปของคุณจะพาเขาไปที่ ActivitySplashScreen หรือ ActivityGameMain หรือไม่
ทมิฬ

คำตอบ:


632

คุณสามารถทำสิ่งนี้ได้โดยการตั้งค่าแอandroid:noHistory ททริบิวเป็น"true"ใน<activity>รายการที่เกี่ยวข้องในAndroidManifest.xmlไฟล์ของคุณ ตัวอย่างเช่น:

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

12
นี่เป็นวิธีที่ดีที่สุดที่จะทำ
shkschneider

22
คุณสามารถใช้FLAG_ACTIVITY_NO_HISTORYอย่างเท่าเทียมกัน
Timmmm

34
ฉันจะได้รับสิ่งนี้จากโค้ดได้อย่างไร เพราะฉันไม่ต้องการทำสิ่งนี้ตลอดเวลา ฉันต้องการลบกิจกรรมที่กำหนดจากประวัติภายใต้เงื่อนไขบางประการเท่านั้น
Namratha

8
เพิ่งทราบว่าการใช้แอตทริบิวต์ noHistory จะทำให้กิจกรรมนั้นเสร็จสิ้นซึ่งอาจทำให้เกิดพฤติกรรมที่ไม่คาดคิดกับการเข้าสู่ระบบ G + ดู: stackoverflow.com/questions/20383878/…เอาฉันสักครู่เพื่อค้นหาข้อผิดพลาดนี้เนื่องจากแอปของฉันยังคงทำงานล้มเหลวโดยไม่มีการติดตามใด ๆ
อะคาปุลโก

13
เป็นการยากที่จะคัดลอกการตั้งค่าสถานะที่จำเป็นเนื่องจากเป็นลิงก์ดังนั้นที่นี่จึงสามารถคัดลอกได้ง่าย android:noHistory="true"
MirroredFate

137

คุณสามารถใช้การส่งต่อเพื่อลบกิจกรรมก่อนหน้าออกจากสแต็กกิจกรรมในขณะที่เรียกใช้กิจกรรมถัดไป มีตัวอย่างนี้ใน APIDemos ที่เป็นแต่โดยทั่วไปสิ่งที่คุณกำลังทำอยู่จะเรียกทันทีหลังจากที่โทรfinish()startActivity()


1
สวัสดีแดเนียลฉันอ่านตัวอย่าง แต่นั่นจะล้างเฉพาะสแต็คประวัติโดย 1 กิจกรรมใช่มั้ย หากสแต็คของฉันดูเหมือน A, B และฉันเปิดตัว C ฉันต้องการให้ C เป็น root ใหม่และชัดเจน A และ B ในตัวอย่างของ sdk การโทรเสร็จสิ้น () จาก B จะทำให้ฉันมี stack A ใช่มั้ย ขอบคุณ
ทำเครื่องหมาย

1
คุณสามารถล้าง A เมื่อคุณเปิดตัว B และล้าง B เมื่อคุณเปิด C อย่างไรก็ตามฉันคิดว่าคุณคงไม่สามารถถอยกลับจาก B ไป A ถ้านั่นคือสิ่งที่คุณต้องการ ฉันจะต้องคิดให้มากกว่านี้หากเป็นปัญหา
Dan Lew

3
ทำเครื่องหมายเพื่อให้บรรลุสิ่งที่คุณต้องการคุณต้องใช้การตั้งค่าสถานะ: FLAG_ACTIVITY_CLEAR_TOP ฉันหวังว่ามันจะช่วย
Francisco Junior

3
FLAG_ACTIVITY_CLEAR_TOPจะไม่ทำงานเพราะ C ไม่ได้อยู่ในกองซ้อนด้านหลัง
Timmmm

1
@DanielLew มีตัวอย่างมากมายใน APIDemos คุณมีชื่อของตัวอย่างที่แนะนำหรือไม่
Stephane

52

ใช่มีลักษณะที่Intent.FLAG_ACTIVITY_NO_HISTORY


46
โปรดทราบว่านี่จะไม่มีการกำหนดประวัติสำหรับกิจกรรมที่คุณกำลังเปิดตัว หากต้องการไม่มีประวัติกิจกรรมที่คุณเปิดตัวฉันแค่ตั้งค่าไว้android:noHistory="true"ในไฟล์ Manifest
georgiecasey

1
มันใช้งานได้ดี ใช้intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)เพื่อตั้งค่าสถานะนี้
vovahost

1
@georgiecasey สิ่งนี้มีประโยชน์เมื่อบางครั้งคุณต้องการเก็บไว้ในประวัติและในบางครั้งคุณไม่ต้องการมันในประวัติศาสตร์
Vihaan Verma

24

นี่เป็นวิธีที่ไม่เหมาะที่จะทำ หากใครมีวิธีที่ดีกว่าฉันจะรอคอยที่จะใช้มัน นี่คือวิธีที่ฉันทำภารกิจนี้ให้สำเร็จด้วย pre-version-11 sdk

ในแต่ละชั้นเรียนที่คุณต้องการจะไปเมื่อถึงเวลาที่ชัดเจนคุณต้องทำสิ่งนี้:

    ... 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();
    }
}

ดังนั้นสิ่งที่จำเป็นต้องตั้งค่าสายโซ่ของ pops จากสแต็กต้องเรียกสิ่งนี้เมื่อคุณต้องการเริ่มต้น:

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

จากนั้นกิจกรรมไม่ได้อยู่ในกอง!
จำคนที่คุณสามารถเริ่มกิจกรรมแล้วเริ่มทำความสะอาดหลังการดำเนินการไม่ปฏิบัติตามเธรดเดียว (ui) เธรด


ในกรณีที่ทุกคนเจอกันในภายหลังฉันคิดว่ามันอาจเป็นสิ่งสำคัญที่จะรู้ว่าถ้าคุณหมุนหน้าจอ Android จะเริ่มต้นแอปพลิเคชันของคุณใหม่ให้คุณเมื่อคุณเปิดกิจกรรมล่าสุดออกจากสแต็ก เพิ่งทราบสิ่งนี้!
เทรวิส

นี่เป็นคำตอบที่ดีถ้าคุณต้องการลบกิจกรรมออกจากสแต็กอย่างมีเงื่อนไขโดยขึ้นอยู่กับสิ่งที่ผู้ใช้ทำในกิจกรรมถัดไป +1
theMothaShip

23

วิธีหนึ่งที่ทำงานได้ก่อน API 11 คือการเริ่มต้นActivityGameMainก่อนจากนั้นในonCreateกิจกรรมนั้นจะเริ่มต้นActivitySplashScreenกิจกรรมของคุณ ActivityGameMainจะไม่ปรากฏในขณะที่คุณเรียก startActivity เร็วเกินไปสำหรับสาด

จากนั้นคุณสามารถล้างสแต็กเมื่อเริ่มต้นActivityGameMainด้วยการตั้งค่าสถานะเหล่านี้ใน Intent:

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

คุณต้องเพิ่มสิ่งนี้ใน ActivitySplashScreen:

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

ActivityGameMainเพื่อให้การกดย้อนกลับไปในกิจกรรมที่ไม่ได้กลับไปที่

ผมถือว่าคุณไม่ต้องการหน้าจอที่จะกลับไปอย่างใดอย่างหนึ่งเพื่อให้บรรลุนี้ผมขอแนะนำการตั้งค่าให้ในของคุณnoHistory AndroidManifest.xmlจากนั้นใส่goBackPressedรหัสในActivitySplashScreenSignUpชั้นเรียนของคุณแทน

อย่างไรก็ตามฉันได้พบวิธีที่จะทำลายสิ่งนี้ เริ่มแอพอื่นจากการแจ้งเตือนขณะที่ActivitySplashScreenSignUpแสดงขึ้นและประวัติหลังจะไม่ถูกรีเซ็ต

วิธีเดียวที่แท้จริงของสิ่งนี้คือใน API 11:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

20

ฉันใช้วิธีนี้

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

ขอบคุณ ฉันพบว่ามีประโยชน์ในกรณีที่มีปุ่มหน้าแรกในเมนูของฉันและฉันไม่ต้องการให้กิจกรรมที่ซ้อนกันปรากฏขึ้นเมื่อผู้ใช้คลิกที่บ้านจากที่นั่น
ghitesh

8

ฉันรู้ว่าฉันมาสาย (เป็นเวลาสองปีแล้วที่คำถามถูกถาม) แต่ฉันก็ทำสิ่งนี้ได้โดยการกดปุ่มย้อนกลับ แทนที่จะตรวจสอบกิจกรรมที่เฉพาะเจาะจงฉันแค่ดูการนับและถ้ามันน้อยกว่า 3 มันก็แค่ส่งแอปไปที่ด้านหลัง (หยุดแอพชั่วคราวและส่งผู้ใช้กลับไปยังสิ่งที่กำลังทำงานอยู่ก่อนเปิดตัว) ฉันตรวจสอบน้อยกว่าสามคนเพราะฉันมีหน้าจออินโทรเดียวเท่านั้น นอกจากนี้ฉันจะตรวจสอบการนับเพราะแอพของฉันอนุญาตให้ผู้ใช้นำทางกลับไปที่หน้าจอหลักผ่านเมนูดังนั้นสิ่งนี้จะช่วยให้พวกเขาสำรองข้อมูลผ่านหน้าจออื่นเช่นปกติหากมีกิจกรรมอื่นนอกเหนือจากหน้าจออินโทรในกองซ้อน

//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

ในรายการคุณสามารถเพิ่ม:

android:noHistory="true"

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

นอกจากนี้คุณยังสามารถโทร

finish()

ทันทีหลังจากเรียก startActivity (.. )


2
ดีกว่าที่จะใช้ค่าสถานะของกิจกรรมกว่าใส่สิ่งต่าง ๆ ในรายการ
Trevor Hart


4

มันบ้าที่ไม่มีใครพูดถึงวิธีแก้ปัญหาอันสง่างามนี้ นี่ควรเป็นคำตอบที่ยอมรับได้

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

ที่สำคัญนี่คือการใช้สำหรับตัวกลางintent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); Activityเมื่อลิงก์กลางนั้นเสียหายแล้วDashActivityครั้งแรกและครั้งสุดท้ายในกองซ้อน

android:noHistory="true"เป็นวิธีการแก้ปัญหาที่ไม่ดีเป็นมันทำให้เกิดปัญหาเมื่ออาศัยเป็นเช่นโทรกลับActivity onActivityResultนี่คือทางออกที่แนะนำและควรได้รับการยอมรับ


1
ธงนั้นฟังดูดีเกินไปที่จะเป็นจริง FLAG_ACTIVITY_NO_HISTORY ทำงานได้ดีและเป็นไปตามที่คาดหวังจนกว่าแอปจะทำให้พื้นหลังเป็นพื้นหลังและทำงานเบื้องหน้าอีกครั้งในขณะที่มีกิจกรรมที่มีการตั้งค่าสถานะที่ด้านบนของสแต็ก เมื่อไปที่พื้นหลังกิจกรรมจะถูกทำลาย เมื่อกลับไปที่แอปหนึ่งจะเห็นกิจกรรมก่อนหน้านี้จากสแต็ก ฉันไม่ต้องการพฤติกรรมเช่นนี้แน่นอน
NeverwinterMoon

4

สายเกินไป แต่หวังว่าจะช่วยได้ คำตอบส่วนใหญ่ไม่ได้ชี้ไปในทิศทางที่ถูกต้อง มีสองธงง่าย ๆ สำหรับสิ่งนั้น

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

จากเอกสาร Android:

FLAG_ACTIVITY_CLEAR_TASK ขั้นสุดท้ายคงที่สาธารณะเพิ่มในระดับ API 11

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

กิจกรรมที่จะถูกล้างก่อนที่กิจกรรมจะเริ่มขึ้น กล่าวคือกิจกรรมกลายเป็นรูทใหม่ของงานที่ว่างเปล่าและกิจกรรมเก่า ๆ จะเสร็จสิ้น สามารถใช้ร่วมกับ FLAG_ACTIVITY_NEW_TASK เท่านั้น


1

เพียงแค่เรียกสิ่งนี้เสร็จสิ้น () ก่อน startActivity (เจตนา) เช่นนี้ -

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

ผู้ใช้ที่มีข้อผิดพลาดเกี่ยวกับ "สิ่งนี้" ควรเปลี่ยนเป็น "ActivityOne.this"
ninbit

1

การลบกิจกรรมออกจากประวัติทำได้โดยการตั้งค่าสถานะก่อนกิจกรรมที่คุณไม่ต้องการ

A-> B-> C-> D

สมมติว่า A, B, C และ D คือ 4 กิจกรรมหากคุณต้องการลบ B และ C จากนั้นตั้งค่าสถานะ

intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

ในกิจกรรม A และ B

นี่คือรหัสบิต

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


-7

ลองสิ่งนี้:

intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)

มันเป็น API Level 1, ตรวจสอบการเชื่อมโยง


2
สิ่งนี้ควรจะทำอย่างไร แน่นอนว่าไม่ได้แก้ปัญหาที่เป็นปัญหา
rodrigo-silveira

คุณแน่ใจว่าคุณไม่ได้หมายความว่าIntent.FLAG_ACTIVITY_NO_HISTORY?
Riot Goes Woof
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.