Android: Bersihkan Stack Aktivitas

132

Saya memiliki beberapa kegiatan dalam aplikasi saya. dan mengalir sangat rumit. Ketika saya mengklik aplikasi Logout menavigasi ke Layar login dan dari sana pengguna dapat keluar dengan tombol batal (menelepon system.exit(0))

ketika saya keluar atau kembali tombol, sistem memanggil suatu kegiatan dari tumpukan :( bagaimana saya bisa menghapus semua kegiatan di tumpukan ketika saya mencapai layar Login? Panggilan finish()tidak praktis karena ada begitu banyak kegiatan dan beberapa kegiatan tidak boleh ditutup ketika mereka aktif seperti aktivitas memohon kamera asli.

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);
Jay Mayu
sumber
Kemungkinan duplikat Android: Bersihkan tumpukan belakang
Mehdi Dehghani

Jawaban:

339

Sebagian besar dari Anda salah. Jika Anda ingin menutup tumpukan aktivitas yang ada terlepas dari apa yang ada di sana dan membuat root baru, set flag yang benar adalah sebagai berikut:

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

Dari dokumen :

public static final int FLAG_ACTIVITY_CLEAR_TASK
Ditambahkan di API level 11

Jika diatur dalam Intent yang diteruskan ke Context.startActivity(), tanda ini akan menyebabkan tugas apa pun yang ada yang terkait dengan aktivitas dihapus sebelum aktivitas dimulai. Yaitu, aktivitas menjadi akar baru dari tugas kosong, dan semua aktivitas lama selesai. Ini hanya bisa digunakan bersamaan dengan FLAG_ACTIVITY_NEW_TASK.

Cynichniy Bandera
sumber
Bekerja dengan sempurna. Terima kasih. Anehnya tidak memberikan kesalahan dengan minSDK = 9.
Mahm00d
Terus terang saya tidak pernah menggunakan fungsi ini, menghidupkan kembali setelah crash, dll, dan lebih fokus pada memperbaiki masalah yang menyebabkan crash)
Cynichniy Bandera
Fungsionalitas yang sama juga disediakan IntentCompat.makeRestartActivityTaskdari pustaka dukungan.
sealskej
Menambahkan hanya dua bendera tersebut meninggalkan jejak tumpukan aktivitas di belakang (dimulai di atas yang sebelumnya), lalu menambahkan Intent.FLAG_ACTIVITY_CLEAR_TOP yang hanya me-restart aplikasi dan kemudian keluar sepenuhnya. Saya belum menambahkan tanda apa pun ke aktivitas secara eksplisit. Apa yang bisa menjadi masalah?
Farid
1
Salah satu awal terbaik: "Sebagian besar dari Anda salah."
nibbana
31

Saat Anda memanggil startActivityaktivitas terakhir yang selalu bisa Anda gunakan

Intent.FLAG_ACTIVITY_CLEAR_TOP

sebagai bendera pada niat itu.

Baca lebih lanjut tentang bendera di sini .

David Olsson
sumber
itu juga tidak membantu. Saya baru saja memunculkan data aktivitas yang tidak diakhiri dengan selesai (); :(
Jay Mayu
Saya kira FLAG_ACTIVITY_CLEAR_TOP menghapus aktivitas di atas. Masalah saya adalah kegiatan di bagian bawah :(
Jay Mayu
Saya kira itu tergantung pada bagaimana sebenarnya alirannya. Anda harus membaca lebih lanjut tentang ini di sini: developer.android.com/reference/android/content/… dan developer.android.com/guide/topics/fundamentals/…
David Olsson
7
Terima kasih telah menunjukkan sumber yang benar. kesalahan yang saya lakukan adalah menutup aktivitas Login. Saya seharusnya tidak menutupnya. Saat aktivitas dimuat pertama kali. jadi ketika saya memanggilnya kembali menggunakan flag Clear_top, aktivitas login membersihkan semua aktivitas di atas. karena login adalah aktivitas entrace pertama, itu membersihkan semua aktivitas yang dimulai setelah. jadi bingo itu bekerja :)
Jay Mayu
13
Dari dokumentasi, FLAG_ACTIVITY_CLEAR_TOP membersihkan tumpukan hanya jika aktivitas spesifik "sudah berjalan dalam tugas saat ini"
AlikElzin-kilaka
16

Berikut adalah metode pembantu sederhana untuk memulai aktivitas baru sebagai aktivitas teratas baru yang bekerja dari API level 4 hingga versi 17 saat ini:

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

sebut saja seperti ini dari aktivitas Anda saat ini:

startNewMainActivity(this, MainActivity.class);
whlk
sumber
1
Tidak bisakah Anda daripada selalu menggunakan intent.addFlags (0x8000); dan menyederhanakan itu?
Davor
Karena bendera ini pertama kali diperkenalkan di Honeycomb, saya tidak tahu apa implikasinya pada versi sebelumnya. Jadi, inilah saya yang menjadi precaucios. Tapi saya rasa penghapusan kondisial seharusnya tidak menjadi masalah.
whlk
1
Anda ingin menambahkan bendera itu ketika level API <11 maka Anda perlu melakukan Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMBhal lain yang intent.addFlags(0x8000);tidak akan pernah ditambahkan
Straw Hat
Saya meminta pengguna untuk melakukan banyak aktivitas satu demi satu melalui niat. Apakah saya perlu melakukan sesuatu untuk memastikan aplikasi tidak macet dengan terlalu banyak aktivitas di stack? Terima kasih!
Ruchir Baronia
9

Kosongkan Aktivitas Kembali dengan kode di bawah ini:

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

Selesai

Hiren Patel
sumber
Saya meminta pengguna untuk melakukan banyak aktivitas satu demi satu melalui niat. Apakah saya perlu melakukan sesuatu untuk memastikan aplikasi tidak macet dengan terlalu banyak aktivitas di stack? Terima kasih!
Ruchir Baronia
@RuchirBaronia, Jika Anda pergi A -> B -> C -> D -> E -> F -> G -> H, sekarang H -> Saya Anda menulis kode saya daripada saya akan menjadi Aktivitas Terakhir setelah itu Anda menekan tombol Kembali aplikasi akan ditutup karena aplikasi tidak memiliki aktivitas di belakang, harap ini akan membantu Anda.
Hiren Patel
Apakah saya perlu melakukan itu? Apa yang akan terjadi jika saya tidak pernah membersihkan tumpukan aktivitas?
Ruchir Baronia
@RuchirBaronia, Backpress: H -> G -> F -> E -> D -> C -> B -> A
Hiren Patel
Tetapi beberapa waktu itu menunjukkan layar putih saat memanggil aktivitas baru. Bagaimana cara mengatasinya?
Sagar
4

Dalam kasus saya, LoginActivity juga ditutup. Hasil dari,

Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK

tidak membantu.

Namun, pengaturan

Intent.FLAG_ACTIVITY_NEW_TASK

membantuku.

Prashant Gami
sumber
Saya meminta pengguna untuk melakukan banyak aktivitas satu demi satu melalui niat. Apakah saya perlu melakukan sesuatu untuk memastikan aplikasi tidak macet dengan terlalu banyak aktivitas di stack? Terima kasih!
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();
Sakib Syed
sumber
1
mengapa Anda menggunakan keduanya this.finish()dan setFlags()juga untuk menghapus aktivitas saat ini?
Sagar
3

Saya mencatat bahwa Anda meminta solusi yang tidak bergantung finish(), tetapi saya ingin tahu apakah ini dapat membantu.

Saya melacak apakah flag keluar dinaikkan dengan variabel kelas statis, yang bertahan seumur hidup seluruh aplikasi. Di setiap kegiatan yang relevanonResume() , gunakan

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

Kelas ExitHelper

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

Katakanlah di mainActivity, pengguna menekan tombol untuk keluar - Anda dapat mengatur ExitHelper.isExitFlagRaised = true;dan kemudian finish(). Setelah itu, kegiatan terkait lainnya yang dilanjutkan secara otomatis akan selesai juga.

Kevin Lee
sumber
apa yang akan terjadi jika saya menggunakan kode di MainActivity onresume () lalu kembali ke aktivitas utama dari aktivitas ke-2 onbackpress
Mithu
3

Keputusan ini berfungsi dengan baik:

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

Tetapi aktivitas baru berjalan lama dan Anda melihat layar putih beberapa saat. Jika ini penting maka gunakan solusi ini:

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

Bagaimana cara menggunakannya:

public class ActivityA extends BaseActivity {

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

Kekurangan: semua aktivitas yang harus ditutup pada stack harus memperluas BaseActivity

maXp
sumber
2

Untuk Pengembang Xamarin, Anda dapat menggunakan:

intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
BYISHIMO Audace
sumber
1

Menggunakan Kotlin:

Anda dapat mengatur bendera secara langsung menggunakan metode setter. Di Kotlin oradalah pengganti untuk bitwise Java atau |.

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

Jika Anda berencana untuk menggunakan ini secara teratur, buat fungsi ekstensi Intent

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

Anda kemudian dapat langsung memanggil fungsi ini sebelum memulai niat

intent.clearStack()
Gibolt
sumber