Android: ล้างกองกิจกรรม


134

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

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

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

1
ตรวจสอบลิงค์นี้ ... stackoverflow.com/questions/5139686/exit-an-android-app/…
xydev

คำตอบ:


345

ส่วนใหญ่คุณคิดผิด หากคุณต้องการปิดสแต็กกิจกรรมที่มีอยู่โดยไม่คำนึงถึงสิ่งที่อยู่ในนั้นและสร้างรูทใหม่ชุดของแฟล็กที่ถูกต้องมีดังต่อไปนี้:

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

จากเอกสาร :

public static final int FLAG_ACTIVITY_CLEAR_TASK
เพิ่มใน API ระดับ 11

หากตั้งค่าไว้ใน Intent ที่ส่งไปยัง Context.startActivity()แฟล็กนี้จะทำให้งานที่มีอยู่ซึ่งจะเกี่ยวข้องกับกิจกรรมถูกล้างออกก่อนที่กิจกรรมจะเริ่มต้น นั่นคือกิจกรรมจะกลายเป็นรูทใหม่ของงานที่ว่างเปล่าและกิจกรรมเก่า ๆ จะเสร็จสิ้น สามารถใช้ร่วมกับFLAG_ACTIVITY_NEW_TASK.


ทำงานได้อย่างสมบูรณ์แบบ ขอบคุณ. แปลกไม่ได้ให้ข้อผิดพลาดกับ minSDK = 9
Mahm00d

ตรงไปตรงมาฉันไม่เคยใช้ฟังก์ชันนี้ฟื้นคืนชีพหลังจากความผิดพลาด ฯลฯ และค่อนข้างมุ่งเน้นไปที่การแก้ไขปัญหาที่ทำให้เกิดความผิดพลาด)
Cynichniy Bandera

ฟังก์ชันเดียวกันยังมีให้IntentCompat.makeRestartActivityTaskจากไลบรารีการสนับสนุน
sealskej

การเพิ่มเฉพาะสองแฟล็กเหล่านี้จะทำให้แทร็กสแต็กกิจกรรมอยู่ข้างหลัง (เริ่มต้นที่ด้านบนของรายการก่อนหน้า) จากนั้นเพิ่ม Intent.FLAG_ACTIVITY_CLEAR_TOP ซึ่งเพียงแค่รีสตาร์ทแอปพลิเคชันจากนั้นออกทั้งหมด ฉันยังไม่ได้เพิ่มการตั้งค่าสถานะใด ๆ ในกิจกรรมอย่างชัดเจน อะไรคือปัญหา?
Farid

1
จุดเริ่มต้นที่ดีที่สุดอย่างหนึ่ง: "พวกคุณส่วนใหญ่คิดผิด"
nibbana

31

เมื่อคุณโทรหาstartActivityกิจกรรมสุดท้ายคุณสามารถใช้ได้ตลอดเวลา

Intent.FLAG_ACTIVITY_CLEAR_TOP

เป็นธงในเจตนานั้น

อ่านเพิ่มเติมเกี่ยวกับธงที่นี่


ที่ยังไม่ช่วย ฉันเพิ่งเปิด dat กิจกรรมไม่ได้ลงท้ายด้วยเสร็จสิ้น (); :(
Jay Mayu

ฉันเดาว่า FLAG_ACTIVITY_CLEAR_TOP จะล้างกิจกรรมที่ด้านบน ปัญหาของฉันคือกิจกรรมที่อยู่ด้านล่าง :(
Jay Mayu

ฉันเดาว่ามันขึ้นอยู่กับว่าการไหลเป็นอย่างไร คุณควรอ่านเพิ่มเติมได้ที่นี่: developer.android.com/reference/android/content/…และdeveloper.android.com/guide/topics/fundamentals/…
David Olsson

7
ขอขอบคุณที่แสดงแหล่งข้อมูลที่ถูกต้อง ความผิดพลาดที่ฉันทำคือการปิดกิจกรรมการเข้าสู่ระบบ ฉันไม่ควรปิดมัน เมื่อกิจกรรมโหลดครั้งแรก ดังนั้นเมื่อฉันเรียกมันกลับมาโดยใช้แฟล็ก Clear_top กิจกรรมการเข้าสู่ระบบจะล้างกิจกรรมทั้งหมดที่อยู่ด้านบน เนื่องจากการเข้าสู่ระบบเป็นกิจกรรมเอนเทรซแรกจึงจะล้างกิจกรรมทั้งหมดที่เริ่มต้นหลังจากนั้น บิงโกมันใช้งานได้ดี :)
Jay Mayu

13
จากเอกสารนี้ FLAG_ACTIVITY_CLEAR_TOP จะล้างสแต็กก็ต่อเมื่อกิจกรรมที่ระบุ "ทำงานอยู่แล้วในงานปัจจุบัน"
AlikElzin-kilaka

16

นี่คือวิธีการช่วยเหลือง่ายๆในการเริ่มกิจกรรมใหม่เป็นกิจกรรมยอดนิยมใหม่ซึ่งใช้ได้ตั้งแต่ระดับ API 4 จนถึงเวอร์ชันปัจจุบัน 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);
}

เรียกสิ่งนี้จากกิจกรรมปัจจุบันของคุณ:

startNewMainActivity(this, MainActivity.class);

1
คุณเป็นไปไม่ได้มากกว่าที่จะใช้ Intent.addFlags (0x8000); และทำให้ง่ายขึ้น?
Davor

เนื่องจากแฟล็กนี้ถูกนำมาใช้ครั้งแรกใน Honeycomb ฉันไม่รู้ว่ามันอาจมีความหมายอะไรในเวอร์ชันก่อนหน้า นี่คือฉันเป็นพรีคอซิโอ แต่ฉันเดาว่าการลบเงื่อนไขไม่น่าจะเป็นปัญหา
whlk

1
คุณต้องการเพิ่มค่าสถานะนั้นเมื่อระดับ API <11 คุณต้องทำBuild.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMBอย่างอื่นintent.addFlags(0x8000);จะไม่ถูกเพิ่ม
หมวกฟาง

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

10

ล้างข้อมูลย้อนหลังกิจกรรมตามรหัสด้านล่าง:

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

เสร็จแล้ว


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

@RuchirBaronia ถ้าคุณไป A -> B -> C -> D -> E -> F -> G -> H ตอนนี้ H -> ฉันเขียนโค้ดของฉันกว่าที่ฉันจะเป็น Last Activity หลังจากนั้นคุณก็กดปุ่มย้อนกลับ แอปจะปิดเนื่องจากแอปไม่มีกิจกรรมสำรองหวังว่านี่จะช่วยคุณได้
Hiren Patel

ฉันจำเป็นต้องทำอย่างนั้นหรือ? จะเกิดอะไรขึ้นถ้าฉันไม่เคยล้างสแต็กกิจกรรม
Ruchir Baronia

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

แต่บางครั้งก็แสดงหน้าจอสีขาวในขณะที่เรียกกิจกรรมใหม่ โฮจะแก้ปัญหานี้?
Sagar

3

ในกรณีของฉัน LoginActivity ก็ถูกปิดเช่นกัน ผลที่ตามมา,

Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK

ไม่ได้ช่วย

อย่างไรก็ตามการตั้งค่า

Intent.FLAG_ACTIVITY_NEW_TASK

ช่วยฉันด้วย


ฉันกำลังให้ผู้ใช้ทำกิจกรรมหลายอย่างทีละกิจกรรมผ่านความตั้งใจ ฉันต้องทำอะไรเพื่อให้แน่ใจว่าแอปไม่ขัดข้องเมื่อมีกิจกรรมในสแต็กมากเกินไป ขอบคุณ!
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
ทำไมคุณถึงใช้ทั้งสองอย่าง this.finish()และsetFlags()เพื่อล้างกิจกรรมปัจจุบัน
Sagar

3

ฉันสังเกตว่าคุณขอวิธีแก้ปัญหาที่ไม่ต้องพึ่งพาfinish()แต่ฉันสงสัยว่าสิ่งนี้อาจช่วยได้หรือไม่

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

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

คลาส ExitHelper

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

พูด Let 's ใน mainActivity ผู้ใช้กดปุ่มเพื่อออก - คุณสามารถตั้งค่าแล้วExitHelper.isExitFlagRaised = true; finish()หลังจากนั้นกิจกรรมอื่น ๆ ที่เกี่ยวข้องซึ่งจะดำเนินการต่อโดยอัตโนมัติก็จะเสร็จสิ้นเช่นกัน


จะเกิดอะไรขึ้นถ้าฉันใช้รหัสใน MainActivity onresume () จากนั้นกลับมาที่ mainactivity จากกิจกรรมที่ 2 onbackpress
Mithu

3

การตัดสินใจนี้ใช้ได้ผลดี:

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

แต่กิจกรรมใหม่เปิดตัวนานและคุณจะเห็นหน้าจอสีขาวบางครั้ง หากสิ่งนี้สำคัญให้ใช้วิธีแก้ปัญหานี้:

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

วิธีใช้:

public class ActivityA extends BaseActivity {

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

ข้อเสีย: กิจกรรมทั้งหมดที่ต้องปิดบนสแต็กต้องขยาย BaseActivity



1

ใช้ Kotlin:

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

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

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

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

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

intent.clearStack()

0

เจตนาเจตนา = เจตนาใหม่ (LoginActivity.this, MainActivity.class); Intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity (เจตนา); เสร็จสิ้น();

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