Android: ลบกิจกรรมก่อนหน้านี้ทั้งหมดออกจากกองหลัง


119

เมื่อฉันคลิกที่ปุ่มออกจากระบบในกิจกรรมโปรไฟล์ของฉันฉันต้องการนำผู้ใช้ไปที่หน้าเข้าสู่ระบบซึ่งเขาต้องใช้ข้อมูลรับรองใหม่

ดังนั้นฉันจึงใช้รหัสนี้:

Intent intent = new Intent(ProfileActivity.this,
        LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

ในonButtonClickปุ่ม Logout

แต่ปัญหาคือเมื่อฉันคลิกปุ่มย้อนกลับอุปกรณ์บนกิจกรรมการเข้าสู่ระบบระบบจะพาฉันไปที่ ProfileActivity ฉันคาดว่าแอปพลิเคชันควรปิดเมื่อฉันกดปุ่มย้อนกลับของอุปกรณ์บน LoginActivity

ผมทำอะไรผิดหรือเปล่า?

ฉันยังเพิ่มandroid:launchMode="singleTop"ในรายการสำหรับLoginActivityของฉันด้วย

ขอบคุณ


@GauravVashisth ฉันเพิ่งทำตามวิธีนี้stackoverflow.com/questions/5794506/…
Archie.bpgc

@ abbas.aniefa วิธีแก้ปัญหานั้นค่อนข้างซับซ้อน เป็นวิธีเดียวที่จะล้างกองหลังทั้งหมด เนื่องจากฉันมีกิจกรรมมากกว่า 30 กิจกรรมดังนั้นฉันจึงควรเขียนโค้ดออกอากาศนี้ให้กับทุกคน
Archie.bpgc

ลองทำตามนี้stackoverflow.com/questions/10961481/… . การใช้ Broadcast เป็นทางออกที่ดีกว่า
abbas.aniefa

อีกวิธีหนึ่งที่คุณสามารถใช้สำหรับการล็อกเอาต์เมื่อคุณออกจากระบบจะเก็บแฟล็กหนึ่งไว้ใน sharedpreferences และในแต่ละวิธี onRestart () ของกิจกรรมคุณสามารถตรวจสอบค่าตัวแปรนี้ได้หากตั้งค่าเป็นจริงคุณจะสามารถสิ้นสุดกิจกรรมปัจจุบันได้ ดังนั้นไม่ว่าจะมีการเปิดกิจกรรมต่างๆมากมายเพียงใด นี่จะเสร็จสิ้นกิจกรรมทั้งหมดของคุณ
Hiren Dabhi

รหัสเดิมของคุณใช้งานได้จริงสำหรับ API ระดับ 11 ขึ้นไปด้วยการปรับแต่ง คุณต้องรวมแฟล็กเข้าด้วยกันในการโทรครั้งเดียว: intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);ฉันได้คำตอบจากคำถามนี้: stackoverflow.com/questions/3473168/…
funnyefe

คำตอบ:


304

วิธีแก้ปัญหาที่เสนอที่นี่ใช้ได้ผลสำหรับฉัน:

ชวา

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);

Kotlin

val i = Intent(this, NewActivity::class.java)
// set the new task and clear flags
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(i)

อย่างไรก็ตามต้องใช้ระดับ API> = 11


พวกคุณอ่านเอกสารของFLAG_ACTIVITY_CLEAR_TASKนี่เป็นวิธีที่เป็นทางการที่จะได้รับ ไม่จำเป็นต้องเปลี่ยนกิจกรรมทั้งหมดในแอป
AlikElzin-kilaka

สิ่งนี้ใช้ไม่ได้กับการแจ้งเตือนstackoverflow.com/questions/24873131/…
แซม

ฉันมี minAPI = 16 ของฉันดังนั้นนี่จึงทำงานได้ดีสำหรับฉัน อย่างไรก็ตามฉันสังเกตเห็นว่าการเรียกใช้มุมมองค่อนข้างช้ากับ API> 21 และราบรื่นด้วย API <21 ใครประสบปัญหาเดียวกัน
แดง M

1
สิ่งนี้จะสร้างงานใหม่สำหรับกิจกรรม
Rohit

@kgiannakakis ไม่ต้องสงสัยเลยว่าวิธีแก้ปัญหาจะใช้งานได้ถ้าเรามีงานเดียว (Activity Back stack) แต่เมื่อเรามีหลายงาน (กองกิจกรรม) มันไม่ทำงาน ตัวอย่างเช่นสมมติว่าฉันมีกิจกรรมสี่อย่างสำหรับแอปพลิเคชัน A, B, C & D สมมติว่าฉันมีกิจกรรมสองกองหลัง A-> B-> C (พื้นหลัง) & D-> A-> B (เบื้องหน้า) และถ้าฉัน เรียกกิจกรรม A จากสแต็กปัจจุบันของฉัน (D-> A-> B) โดยมีจุดประสงค์กรองสิ่งที่คุณแนะนำว่าจะเกิดอะไรขึ้นให้ล้างสแต็กปัจจุบันของฉัน (D-> A-> B) และเปิดกิจกรรม A และเมื่อฉันกดกลับเข้าไปใกล้ แอพพลิเคชั่น แต่ถ้าฉันกดปุ่มแอพล่าสุดฉันจะเห็นสองแอพด้านหลังของฉันที่นั่น
Rahul Pareta

31

นี่คือวิธีแก้ปัญหาหนึ่งในการล้างกิจกรรมทั้งหมดของแอปพลิเคชันของคุณเมื่อคุณใช้ปุ่มออกจากระบบ

ทุกครั้งที่คุณเริ่มกิจกรรมให้เริ่มในลักษณะนี้:

Intent myIntent = new Intent(getBaseContext(), YourNewActivity.class);
startActivityForResult(myIntent, 0);

เมื่อคุณต้องการปิดแอปทั้งหมดให้ดำเนินการดังนี้:

setResult(RESULT_CLOSE_ALL);
finish();

RESULT_CLOSE_ALL เป็นตัวแปรส่วนกลางขั้นสุดท้ายที่มีจำนวนเต็มที่ไม่ซ้ำกันเพื่อส่งสัญญาณว่าคุณต้องการปิดกิจกรรมทั้งหมด

จากนั้นกำหนดการonActivityResult(...)เรียกกลับของทุกกิจกรรมดังนั้นเมื่อกิจกรรมส่งกลับด้วยค่า RESULT_CLOSE_ALL จะเรียกfinish():

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(resultCode)
    {
    case RESULT_CLOSE_ALL:
        setResult(RESULT_CLOSE_ALL);
        finish();
    }
    super.onActivityResult(requestCode, resultCode, data);
}

สิ่งนี้จะทำให้เกิดเอฟเฟกต์น้ำตกที่ปิดกิจกรรมทั้งหมดของคุณ

อย่างไรก็ตามนี่เป็นการแฮ็กและใช้startActivityForResultในลักษณะที่ไม่ได้ออกแบบมาให้ใช้

บางทีวิธีที่ดีกว่าในการทำเช่นนี้คือการใช้เครื่องรับสัญญาณออกอากาศดังที่แสดงไว้ที่นี่:

เมื่อออกจากระบบให้ล้างสแต็กประวัติกิจกรรมป้องกันไม่ให้ปุ่ม "ย้อนกลับ" เปิดกิจกรรมที่ลงชื่อเข้าใช้เท่านั้น

ดูหัวข้อเหล่านี้สำหรับวิธีการอื่น ๆ เช่นกัน:

Android: ล้างสแต็กด้านหลัง

เสร็จสิ้นกิจกรรมก่อนหน้านี้ทั้งหมด


4
เป็นไปได้ไหมเมื่อคุณมีกิจกรรมเกี่ยวกับประวัติศาสตร์ประมาณ 30 รายการ ??
Rakesh Gondaliya

4
ควรจะเป็น. แต่ถ้าคุณมี 30 กิจกรรมในประวัติศาสตร์คุณอาจต้องพิจารณาเปลี่ยนการออกแบบของคุณ 30 ดูเหมือนจะมากเกินไปและ Android อาจฆ่าพวกมันเอง
Anup Cowkur

1
นี่เป็นวิธีที่ไม่ดีในการทำ คำถามคำตอบของ @RakeshGondaliya ดูเหมือนถูกกฎหมาย 30 อาจเป็นเพียงตัวเลขที่แสดงถึงกิจกรรมที่ 'สูง' คำตอบนี้ดูดีกว่า: stackoverflow.com/a/3008684/243709
Aman Alam

คำตอบนี้ดีมาก คุณยังสามารถใช้ไลบรารี EventBus เพื่อส่งกิจกรรมไปยังกิจกรรมของคุณในแบ็ค github.com/greenrobot/EventBus
สแตน

ดีกว่าที่จะใช้การตั้งค่าสถานะ 'Intent.FLAG_ACTIVITY_CLEAR_TOP' ที่เรียบง่ายด้วยความตั้งใจ
Naveen Rao

18

หากต้องการล้างสแต็กกิจกรรมโดยสมบูรณ์คุณต้องการสร้างกองงานใหม่โดยใช้ TaskStackBuilder ตัวอย่างเช่น:

Intent loginIntent = LoginActivity.getIntent(context);
TaskStackBuilder.create(context).addNextIntentWithParentStack(loginIntent).startActivities();

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


1
วิธีนี้เป็นวิธีที่ดีที่สุด
Paul Burke

FLAG_ACTIVITY_NEW_TASKหรือfinishAffinity()ไม่ได้ผลสำหรับฉัน คำตอบนี้เท่านั้นที่แก้จุดประสงค์ได้
TM

หากฉันออกจากแอปผ่านปุ่มย้อนกลับและกลับผ่านไอคอนแอปจะเปิดขึ้นในกิจกรรมที่ฉันเรียกวิธีนั้น ดังนั้นไม่ทำงานสำหรับฉัน
Tgo1014

17

finishAffinity()เพิ่มใน API 16 ใช้ActivityCompat.finishAffinity()ในเวอร์ชันก่อนหน้า เมื่อคุณจะเริ่มกิจกรรมใด ๆ โดยใช้ความตั้งใจและเสร็จสิ้นกิจกรรมปัจจุบัน ตอนนี้ใช้ ActivityCompat.finishAffinity()แทนfinish(). จะเสร็จสิ้นกิจกรรมที่ซ้อนกันทั้งหมดด้านล่างกิจกรรมปัจจุบัน มันใช้ได้ดีสำหรับฉัน


3
จริงๆแล้วActivityCompat.finishAffinity()
The Berga

finishAffinity()ยังเสร็จสิ้นกิจกรรมปัจจุบันด้วยกิจกรรมทั้งหมดที่มีอยู่ในกองหลังของความสัมพันธ์เดียวกัน
Neeraj Sewani

10

อะไรที่เหมาะกับฉัน

Intent intent = new Intent(getApplicationContext(), HomeActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);

5

ทางออกหนึ่งที่เป็นไปได้สิ่งที่ฉันจะแนะนำให้คุณคือการเพิ่มandroid:launchMode="singleTop"ในประจักษ์สำหรับฉันProfileActivity และเมื่อออกจากระบบคลิก u สามารถออกจากระบบ เริ่มต้นอีกครั้งคุณLoginActivity เมื่อออกจากระบบคุณสามารถเรียกสิ่งนี้ได้

Intent in = new Intent(Profile.this,Login.class);
                in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(in);
                finish();

ฉันทำสิ่งนี้สิ่งที่เกิดขึ้นคือ: เมื่อฉันคลิกปุ่มย้อนกลับมันจะพาฉันไปที่ Activty จากที่ฉันมาที่ ProfileActivity
Archie.bpgc

สิ่งนี้อาจเกิดขึ้นเนื่องจากคุณเข้ามาที่ ProfileActivity โดยเรียกเจตนาใหม่โดยไม่เรียกว่า finish (); คุณมาที่ ProfileActivity จากกิจกรรมอื่น ๆ นอกเหนือจาก LoginActivty ได้อย่างไร?
Android

ฉันกำลังข้ามคำถามเดิม ๆ ฉันคิดว่ามันจะไม่ได้ผลเมื่อเจตนาในการเข้าสู่ระบบถูกทำลายโดยระบบกล่าวว่าเนื่องจากไม่มี memroy
user1914692

5

สำหรับ API 11+ คุณสามารถใช้Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASKสิ่งนี้:

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

มันจะล้างกิจกรรมก่อนหน้าทั้งหมดและเริ่มกิจกรรมใหม่


4

คุณสามารถลองfinishAffinity()ปิดกิจกรรมปัจจุบันทั้งหมดและใช้งานได้บน Android 4.1 ขึ้นไป


1
FinishAffinity () ที่เพิ่มใน API 16 ใช้ ActivityCompat.finishAffinity () ในเวอร์ชันก่อนหน้า ฉันทำงานได้ดีสำหรับฉัน
Anurag Srivastava

2

ฉันก็ประสบปัญหาเดียวกัน ..

ในกิจกรรมการเข้าสู่ระบบสิ่งที่ฉันทำคือ

    Intent myIntent = new Intent(MainActivity.this, ActivityLoggedIn.class);
    finish();
    MainActivity.this.startActivity(myIntent);  

เมื่อออกจากระบบ

   Intent myIntent = new Intent(ActivityLoggedIn.this, MainActivity.class);
   finish();
   ActivityLoggedIn.this.startActivity(myIntent);

สิ่งนี้ใช้งานได้ดี แต่เมื่อฉันอยู่ใน ActivityLoggedIn และฉันย่อขนาดแอปแล้วคลิกที่ไอคอนปุ่มตัวเรียกใช้งานบนลิ้นชักแอป MainActivity จะเริ่มต้นอีกครั้ง: - / ฉันใช้แฟล็ก

android:LaunchMode:singleTask 

สำหรับ MainActivity


2

ใช้สิ่งต่อไปนี้สำหรับ activity

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

ลบแฟล็ก CLEAR_TASKสำหรับการใช้แฟรกเมนต์

ฉันหวังว่านี่อาจใช้สำหรับบางคน


1

แค่เก็บ

Intent intent = new Intent(ProfileActivity.this,
    LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
startActivity(intent);

4
มันไม่ทำงาน ฉันยังสามารถไปที่ ProfileActivity โดยใช้ปุ่มย้อนกลับ
Archie.bpgc

1

ไม่มีแฟล็กเจตนาใดที่ใช้ได้ผลสำหรับฉัน แต่นี่คือวิธีที่ฉันแก้ไข:

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


1

ลองใช้วิธีนี้จะได้ผล:

Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();

1

ใน API ระดับ 11 ขึ้นไปให้ใช้FLAG_ACTIVITY_CLEAR_TASKและFLAG_ACTIVITY_NEW_TASKตั้งค่าสถานะบน Intent เพื่อล้างสแต็กกิจกรรมทั้งหมด

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |  Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);

0

ใช้สิ่งนี้

Intent i1=new Intent(getApplicationContext(),StartUp_Page.class);
i1.setAction(Intent.ACTION_MAIN);
i1.addCategory(Intent.CATEGORY_HOME);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i1);
finish();

คุณรู้จัก setFlags และ addFlags หรือไม่
GvSharma


0

Kotlin ขั้นสูงนำกลับมาใช้ใหม่ได้:

คุณสามารถตั้งค่าแฟล็กโดยตรงโดยใช้เมธอด setter ใน Kotlin orคือการแทนที่ Java bitwise หรือ|.

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

หากคุณวางแผนที่จะใช้สิ่งนี้เป็นประจำให้สร้างฟังก์ชันส่วนขยายเจตนา

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

จากนั้นคุณสามารถเรียกใช้ฟังก์ชันนี้ได้โดยตรงก่อนที่จะเริ่มเจตนา

intent.clearStack()

หากคุณต้องการตัวเลือกในการเพิ่มแฟล็กเพิ่มเติมในสถานการณ์อื่น ๆ ให้เพิ่มพารามิเตอร์ที่เป็นทางเลือกให้กับฟังก์ชันส่วนขยาย

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.