Bagaimana saya bisa kembali ke aktivitas orang tua dengan benar?

179

Saya memiliki 2 aktivitas (A dan B) di aplikasi android saya dan saya menggunakan maksud untuk beralih dari aktivitas A ke aktivitas B. Penggunaan parent_activity diaktifkan:

 <activity
        android:name=".B"
        android:label="B" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.app_name.A" />
  </activity>

Saya juga menggunakan tema yang menyediakan tombol-UP.

Jadi setelah saya menelepon aktivitas BI dapat menggunakan tombol-UP untuk kembali ke aktivitas A. Masalahnya adalah aplikasi tersebut sepertinya memanggil onCreate () -fungsi dari aktivitas A lagi dan ini bukan perilaku yang saya butuhkan. Saya membutuhkan aktivitas A agar terlihat sama seperti sebelum saya menelepon aktivitas B.

Apakah ada cara untuk mencapai ini?

Terima kasih sebelumnya

EDIT:

Saya tidak menulis kode apa pun untuk memulai aktivitas B dari aktivitas A. Saya pikir ini dibuat otomatis oleh gerhana.

Kelas B terlihat seperti:

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_b, menu);
    return true;
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            return true;
    }
    return super.onOptionsItemSelected(item);
}
ashiaka
sumber
Posting kode Anda, untuk memulai Kegiatan A dari B ..
user370305
Jika saya mengerti Anda benar, Anda dapat menggunakan startActivityForResult () dan mengembalikan resultCode atau sesuatu.
Law Gimenez
Harap perbarui jawaban yang benar yang ditandai ini! Jawaban yang BENAR berasal dari LorenzCK - bukan dari pengguna ......! Memberi tag ini sebagai benar menyesatkan dan membuat lebih banyak programmer salah paham navigasi dibandingkan dengan navigasi belakang!
Zordid
Wah, banyak sekali jawaban yang salah di sini, bisakah Anda membantu membersihkan ini ...?
Zordid
@ashiaka - Jawaban yang benar sesuai desain kode Anda diperbarui.
user370305

Jawaban:

334

Anda mendeklarasikan aktivitas A dengan standar launchModedi manifes Android. Menurut dokumentasi , itu berarti yang berikut:

Sistem selalu membuat instance baru dari aktivitas dalam tugas target dan mengarahkan maksudnya.

Oleh karena itu, sistem dipaksa untuk membuat kembali aktivitas A (yaitu panggilan onCreate) bahkan jika tumpukan tugas ditangani dengan benar.

Untuk memperbaiki masalah ini, Anda perlu mengubah manifes, menambahkan atribut berikut ke deklarasi aktivitas A:

android:launchMode="singleTop"

Catatan: menelepon finish()(seperti yang disarankan sebagai solusi sebelumnya) hanya berfungsi bila Anda benar - benar yakin bahwa aktivitas B misalnya Anda mengakhiri hidup di atas instance aktivitas A. Dalam alur kerja yang lebih kompleks (misalnya, meluncurkan aktivitas B dari pemberitahuan) ini mungkin tidak terjadi dan Anda harus benar memulai aktivitas A dari B.

LorenzCK
sumber
11
Berikut adalah penjelasan dari dokumen Android, Mode "standar" dan "singleTop" berbeda satu sama lain hanya dalam satu hal: Setiap kali ada niat baru untuk aktivitas "standar", instance baru kelas dibuat untuk merespons niat itu. Setiap instance menangani satu niat. Demikian pula, contoh baru dari aktivitas "singleTop" juga dapat dibuat untuk menangani maksud baru. Namun, jika tugas target sudah memiliki instance aktivitas yang ada di bagian atas stacknya, instance tersebut akan menerima maksud baru (dalam panggilan onNewIntent ()); contoh baru tidak dibuat.
kpsfoo
Perhatikan bahwa menurut dokumentasi navigateUpFromSameTask(...) harus ditambahkan FLAG_ACTIVITY_CLEAR_TOPke upIntent(melalui navigateUpTo(...)yang harus menghasilkan perilaku yang sama (sesuai dengan panduan ini ), tetapi bendera tidak pernah ditetapkan - dan karena itu jawaban ini masuk akal
Anigif
82

Jawaban Diperbarui: Desain Navigasi Atas

Anda harus mendeklarasikan aktivitas mana yang merupakan induk yang tepat untuk setiap aktivitas. Melakukannya memungkinkan sistem untuk memfasilitasi pola navigasi seperti Naik karena sistem dapat menentukan aktivitas induk logis dari file manifes.

Jadi untuk itu Anda harus mendeklarasikan Aktivitas induk Anda di tag Activity dengan atribut

android:parentActivityName

Suka,

<!-- The main/home activity (it has no parent activity) -->
    <activity
        android:name="com.example.app_name.A" ...>
        ...
    </activity>
    <!-- A child of the main activity -->
    <activity
        android:name=".B"
        android:label="B"
        android:parentActivityName="com.example.app_name.A" >
        <!-- Parent activity meta-data to support 4.0 and lower -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.app_name.A" />
    </activity>

Dengan aktivitas induk yang dideklarasikan dengan cara ini, Anda dapat menavigasi ke induk yang sesuai seperti di bawah ini,

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    // Respond to the action bar's Up/Home button
    case android.R.id.home:
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Jadi, ketika Anda memanggil NavUtils.navigateUpFromSameTask(this);metode ini, ia menyelesaikan aktivitas saat ini dan memulai (atau melanjutkan) aktivitas induk yang sesuai. Jika aktivitas induk target ada di tumpukan belakang tugas, itu diajukan seperti yang didefinisikan oleh FLAG_ACTIVITY_CLEAR_TOP.

Dan untuk menampilkan tombol Atas Anda harus mendeklarasikan setDisplayHomeAsUpEnabled():

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

Jawaban Lama: (Tanpa Navigasi Naik, Navigasi Kembali bawaan)

Itu terjadi hanya jika Anda memulai kembali Kegiatan A dari Kegiatan B.

Menggunakan startActivity().

Alih-alih dari Aktivitas A, mulai Kegiatan B menggunakan startActivityForResult()dan menimpa onActivtyResult()di Aktivitas A.

Sekarang di Aktivitas B cukup panggil finish()tombol Naik. Jadi sekarang Anda diarahkan ke Activity A onActivityResult()tanpa membuat Activity A lagi ..

pengguna370305
sumber
Saya tidak tahu di mana startActivity () dalam aktivitas B disebut. Saya telah memposting kode sumber aktivitas B ...
ashiaka
18
Alih-alih NavUtils.navigateUpFromSameTask(this); menulis baris kode finish().
user370305
4
Itu menimbulkan pertanyaan, mengapa Google tidak menyebutkan apa-apa tentang finish()atau startActivityForResult()dalam dokumentasi mereka tentang Navigasi ( developer.android.com/design/patterns/navigation.html )?
wired00
ini terdengar seperti solusi yang melelahkan. @LorenzCK sepertinya jauh lebih baik.
carmen_munich
Terima kasih banyak telah menggunakan NavUtils.navigateUpFromSameTask (ini). Besar plus! Saya telah mencari metode seperti ini untuk mengganti selesai () yang tidak kembali ke aktivitas induk dalam beberapa keadaan. finish () pada dasarnya akan kembali ke aktivitas sebelumnya yang tidak harus aktivitas induk.
Hong
22

Saya memiliki pengaturan yang hampir sama yang mengarah ke perilaku yang tidak diinginkan yang sama. Bagi saya ini berhasil: menambahkan atribut berikut ke aktivitas A di Manifest.xmlaplikasi saya:

android:launchMode="singleTask"

Lihat artikel ini untuk penjelasan lebih lanjut.

androidnewbie
sumber
1
Dari sudut pandang saya solusi yang tepat untuk masalah tersebut. Ini akan berperilaku seperti jika Anda memanggil selesai () jika Kegiatan ada di tumpukan tugas. Jika tidak, ini akan dibuat dan dimulai.
Johan
5
Ini bukan cara yang benar karena akan membuat tugas baru yang tidak perlu setiap kali, Anda harus menggunakan launchMode = "singleTop".
kpsfoo
19

Meskipun merupakan pertanyaan lama, inilah solusi (imho yang terbersih dan terbaik) yang lain karena semua jawaban sebelumnya tidak berhasil bagi saya karena saya mendalami Aktivitas B dari Widget .

public void navigateUp() {
final Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent) || isTaskRoot()) {
    Log.v(logTag, "Recreate back stack");
        TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent).startActivities();
  } else {
    NavUtils.navigateUpTo(this, upIntent);
  }
}

[ https://stackoverflow.com/a/31350642/570168 ]

Tetapi juga lihat: https://speakerdeck.com/jgilfelt/this-way-up-implementing-effective-navigation-on-android

Tobias
sumber
7

Cara yang lebih baik untuk mencapai ini adalah dengan menggunakan dua hal: panggilan:

NavUtils.navigateUpFromSameTask(this);

Sekarang, agar ini berfungsi, Anda harus memiliki file manifes Anda menyatakan bahwa aktivitas A memiliki aktivitas induk B. Aktivitas induk tidak memerlukan apa-apa. Di versi 4 dan di atas Anda akan mendapatkan panah kembali yang bagus tanpa upaya tambahan (ini dapat dilakukan pada versi yang lebih rendah juga dengan sedikit kode, saya akan meletakkannya di bawah) Anda dapat mengatur data ini di tab aplikasi manifest-> di GUI (gulir ke bawah ke nama aktivitas induk, dan letakkan dengan tangan)

Node pendukung:

jika Anda ingin mendukung versi di bawah versi 4, Anda harus memasukkan metadata juga. klik kanan pada aktivitas, tambahkan-> meta data, nama = android.support.PARENT_ACTIVITY dan nilai = your.full.activity.name

untuk mendapatkan panah yang bagus di versi yang lebih rendah juga:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

harap dicatat Anda akan membutuhkan dukungan perpustakaan versi 7 untuk membuat semua ini berfungsi, tetapi itu sangat berharga!

donald
sumber
5

Apa yang berhasil bagi saya adalah menambahkan:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onBackPressed() {
        finish();
    }

ke TheRelevantActivity.javadan sekarang berfungsi seperti yang diharapkan

dan ya jangan lupa menambahkan:

getSupportActionbar.setDisplayHomeAsUpEnabled(true);dalam onCreate()metode

Hammad Nasir
sumber
4

Saya mencoba android:launchMode="singleTask", tetapi itu tidak membantu. Bekerja untuk saya gunakanandroid:launchMode="singleInstance"

Pnemonik
sumber
Menambahkan android: launchMode = "singleInstance" ke aktivitas induk menyelesaikan masalah untuk saya
emir
4

Menambah jawaban @ LorenCK, ubah

NavUtils.navigateUpFromSameTask(this);

ke kode di bawah ini jika aktivitas Anda dapat dimulai dari aktivitas lain dan ini dapat menjadi bagian dari tugas yang dimulai oleh beberapa aplikasi lain

Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
    TaskStackBuilder.create(this)
            .addNextIntentWithParentStack(upIntent)
            .startActivities();
} else {
    NavUtils.navigateUpTo(this, upIntent);
}

Ini akan memulai tugas baru dan memulai Aktivitas induk Aktivitas Anda yang dapat Anda tetapkan dalam Manifest seperti di bawah ini dari versi Min SDK <= 15

<meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.example.app_name.A" />

Atau menggunakan parentActivityNamejika> 15

Sourabh
sumber
Catatan: Apakah menyatakan parentActivityNameuntuk SDK> 15 atau yang lain itu akan memberi Anda beberapa crash acak
Sourabh
3

Saya memiliki masalah serupa menggunakan Android 5.0 dengan nama aktivitas orang tua yang buruk

<activity
        android:name=".DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName=".MainActivity" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity" />
    </activity>

Saya menghapus com.example.myfirstapp dari nama aktivitas induk dan itu berfungsi dengan baik

Patrick Bergthold
sumber
2

Tambahkan ke informasi manifes aktivitas Anda dengan atribut

android:launchMode="singleTask"

bekerja dengan baik untuk saya

Pravesh Kumar
sumber
1
Alur yang lengkap adalah seperti @Override public boolean onOptionsItemSelected (item MenuItem) {switch (item.getItemId ()) {case android.R.id.home: NavUtils.navigateUpFromSameTask (this); kembali benar; } kembalikan super.onOptionsItemSelected (item); }
Pravesh Kumar
Tambahkan ke manifes <aktivitas android Anda: name = ". MainActivity" android: label = "@ string / title_activity_main"> </activity> <activity android: name = ". CreateEventActivity" android: label = "@ string / title_activity_create_event" android : launchMode = "singleTask" android: parentActivityName = ". MainActivity"> <meta-data android: name = "android.support.PARENT_ACTIVITY" android: value = ". MainActivity" /> </activity>
Pravesh Kumar
2

Di kelas Java: -

    toolbar = (Toolbar) findViewById(R.id.apptool_bar);
    setSupportActionBar(toolbar);

    getSupportActionBar().setTitle("Snapdeal");

    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

Dalam Manifes: -

<activity
            android:name=".SubActivity"
            android:label="@string/title_activity_sub"
            android:theme="@style/AppTheme" >
            <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity"></meta-data>
    </activity>

Itu akan membantumu

Kasthuri Shravankumar
sumber
1
    @Override
public boolean onOptionsItemSelected(MenuItem item) {
   switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
    case android.R.id.home:
        finish();
        return true;
}
return super.onOptionsItemSelected(item);

seperti tekan Kembali

Dan Alboteanu
sumber
1

coba ini:

Intent intent;
@Override
public void onCreate(Bundle savedInstanceState) {
    intent = getIntent();   
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_b, menu);
    return true;
}  

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpTo(this,intent);
            return true;
    }
    return super.onOptionsItemSelected(item);
}
Luis Valadez
sumber
0

Pergi ke manifes saya dan menambahkan android:launchMode="singleTop" aktivitas tersebut membantu saya.

Ini secara khusus menyelesaikan masalah saya karena saya tidak ingin Android membuat contoh baru dari aktivitas sebelumnya setelah memukul Up tombol di toolbar - Saya malah ingin menggunakan instance yang ada dari aktivitas sebelumnya ketika saya naik hierarki navigasi.

Referensi: android: launchMode

mumush
sumber