Soalan dan skop
Anda menyelenggara aplikasi Android yang besar dengan Activity, Fragment, dan skrin Compose. Mulai Android 15, pengguna boleh melihat pratonton kembali sistem, tetapi skrin legasi masih memintas butang kembali dengan onBackPressed atau KeyEvent.KEYCODE_BACK. Hasilnya ialah ketiadaan animasi, logik pengesahan pada masa yang salah, atau keadaan yang tertinggal selepas gerak isyarat dibatalkan. Penemuduga inginkan pelan migrasi dan ujian secara berperingkat.
Anggap bahawa Android 13 dan versi seterusnya mesti terus disokong dan timbunan navigasi tidak boleh ditulis semula secara serentak. Android mengesyorkan OnBackPressedCallback yang serasi ke belakang, atau OnBackInvokedCallback platform apabila integrasi sistem secara langsung diperlukan. Compose menggunakan PredictiveBackHandler apabila kemajuan gerak isyarat diperlukan.
Perkara yang dinilai oleh penemuduga
- Sama ada anda memodelkan predictive back sebagai pratonton yang diikuti oleh komit atau pembatalan, bukan sebagai klik sekali gus.
- Sama ada pemintasan legasi beralih ke panggilan balik AndroidX yang status didayakannya mengikut keadaan UI.
- Sama ada anda mengasingkan panggilan balik animasi UI daripada pemerhati pengelogan atau perniagaan supaya animasi sistem tidak terhalang.
- Sama ada anda menerangkan susunan panggilan balik Compose, pemulihan pembatalan, dan keserasian View/Fragment.
- Sama ada anda merangkumi animasi sistem Android 15, pilihan keluar (opt-out) di peringkat aktiviti, dan ujian peranti yang boleh diulang.
Jawapan yang lemah menyatakan "naik taraf AndroidX dan hidupkan bendera." Jawapan yang kukuh mentakrifkan tanggungjawab panggilan balik, pemulihan pembatalan idempoten, dan pelancaran aktiviti demi aktiviti.
Penjelasan sebelum menjawab
- Adakah skrin menggunakan Fragment/Navigation Component, Compose, atau timbunan kembali Activity tersuai? Ini menentukan API migrasi.
- Adakah butang kembali mesti mengesahkan borang yang belum disimpan? Panggilan balik mesti mengikut keadaan UI sebelum gerak isyarat, bukan memutuskan selepas ia selesai.
- Adakah kemajuan gerak isyarat diperlukan untuk animasi tersuai? Gunakan
BackHandleruntuk pemintasan akhir danPredictiveBackHandlerhanya apabila kemajuan diperlukan. - Adakah sasaran merangkumi Android 15? Animasi sistem dan ujian berbeza, manakala lapisan keserasian mesti merangkumi keluaran yang lebih lama.
- Bolehkah aplikasi dilancarkan mengikut Activity atau skrin? Aplikasi yang besar boleh menggunakan bendera
enableOnBackInvokedCallbackdi peringkat aktiviti.
Jawapan ini mengubah reka bentuk: kekalkan panggilan balik yang mudah apabila kemajuan tidak diperlukan, laksanakan pemulihan untuk keadaan borang, dan hijrahkan skrin AndroidX sebelum membuang setiap pemintasan legasi.
Rangka kerja jawapan 30 saat
"Saya menginventori setiap pemintasan kembali legasi dan mengikat panggilan balik kepada keadaan UI yang boleh diperhatikan. Saya menggantikan pemintasan onBackPressed dan KEYCODE_BACK dengan OnBackPressedCallback; saya menggunakan OnBackInvokedCallback hanya untuk integrasi platform langsung, dan PredictiveBackHandler dalam Compose apabila saya memerlukan kemajuan. Pratonton hanya menukar visual yang boleh berbalik. Gerak isyarat yang dikomitkan akan menavigasi atau mengesahkan; gerak isyarat yang dibatalkan akan memulihkan snapshot permulaan. Panggilan balik keutamaan lalai atau tindanan boleh menyekat animasi sistem, jadi animasi UI dan pengelogan perniagaan menggunakan laluan berasingan. Saya melancarkan ini mengikut Activity dan menguji pada Android 13, 14, dan 15."
Penyelesaian langkah demi langkah
1. Modelkan kembali sebagai mesin keadaan
Anggap gerak isyarat sebagai idle → preview(progress) → committed atau idle → preview(progress) → cancelled. Pratonton hanya mengemas kini visual yang boleh berbalik. Komit melakukan navigasi, penolakan, atau pengesahan. Pembatalan memulihkan snapshot. Tiada penulisan perniagaan yang tidak boleh ditarik balik patut berlaku dalam tempoh apabila pengguna masih boleh melepaskan gerak isyarat.
2. Hijrahkan API pemintasan legasi
Laluan keserasian Android adalah dengan menaik taraf AndroidX Activity dan mendaftarkan OnBackPressedCallback dengan OnBackPressedDispatcher. Berhenti memintas dalam Activity.onBackPressed atau KeyEvent.KEYCODE_BACK. Gunakan OnBackInvokedCallback apabila integrasi kembali peringkat platform diperlukan. KEYCODE_BACK masih mempunyai kegunaan yang disokong, tetapi ia tidak sepatutnya menjadi titik masuk pemintasan kembali lagi.
val confirmCallback = object : OnBackPressedCallback(false) {
override fun handleOnBackPressed() {
showDiscardDialog()
}
}
onBackPressedDispatcher.addCallback(viewLifecycleOwner, confirmCallback)
formState.collect { state ->
confirmCallback.isEnabled = state.hasUnsavedChanges
}Keadaan didayakan datang daripada keadaan borang yang boleh diperhatikan, bukan semakan lewat selepas panggilan balik dicetuskan. Apabila borang bersih, lumpuhkan panggilan balik supaya sistem atau komponen navigasi mengendalikan kembali.
3. Kendalikan kemajuan dan pembatalan Compose
Gunakan PredictiveBackHandler untuk mengumpul BackEventCompat apabila skrin Compose memerlukan animasi yang dipacu oleh kemajuan. Pulihkan animasi dan keadaan berperingkat apabila pengumpulan dibatalkan atau gerak isyarat tidak dikomitkan. Gunakan BackHandler untuk pemintasan akhir tanpa kemajuan supaya skrin mudah tidak membawa logik gerak isyarat yang tidak perlu.
PredictiveBackHandler(enabled = canNavigateBack) { progress ->
try {
progress.collect { event -> renderPreview(event.progress) }
navigateBack()
} catch (cancelled: CancellationException) {
restorePreviewState()
}
}Panggilan balik diproses sebagai timbunan: panggilan balik aktif yang terakhir ditambah akan mengendalikan gerak isyarat seterusnya. Dalam Compose bersarang, PredictiveBackHandler atau BackHandler yang paling dalam akan menang, jadi elakkan panggilan balik global yang samar-samar.
4. Jangan sekat animasi sistem
Panduan Android menyatakan bahawa OnBackPressedCallback atau OnBackInvokedCallback pada PRIORITY_DEFAULT atau PRIORITY_OVERLAY menghalang animasi sistem prediktif dan memaksa aplikasi mengendalikan animasi tersebut. Panggilan balik UI harus mengawal dialog dan peralihan. Pengelogan atau pemerhatian perniagaan harus menggunakan laluan pemerhatian bukan menyekat dan bukannya panggilan balik berkeutamaan tinggi yang menyekat sistem.
5. Lancarkan mengikut Activity
Tetapkan android:enableOnBackInvokedCallback di peringkat aplikasi atau gantikannya untuk satu Activity. Aplikasi yang besar boleh mendayakannya untuk Activity yang telah dihijrahkan manakala skrin legasi menarik diri buat sementara waktu, kemudian membuang pemintasan lama satu skrin pada satu masa. Mematikan bendera ini akan mengabaikan OnBackInvokedCallback, tetapi AndroidX OnBackPressedCallback masih boleh berjalan, jadi uji kedua-dua laluan secara berasingan.
6. Uji komit, pembatalan, dan sempadan
Untuk setiap skrin, uji: pelepasan sebelum ambang komit; pelepasan selepas ambang; borang kotor dan bersih; panggilan balik Fragment/Compose bersarang; kembali dari Activity akar ke skrin utama sistem; serta Android 13, 14, dan 15. Sahkan timbunan navigasi, data borang, keadaan animasi akhir, dan keadaan didayakan panggilan balik, bukan sekadar tangkapan skrin.
Contoh jawapan berkualiti tinggi
"Saya akan memodelkan kembali sebagai mesin keadaan yang boleh dibatalkan dan menginventori pemintasan legasi dalam Activity, Fragment, dan Compose. Migrasi keserasian menggunakan OnBackPressedCallback; OnBackInvokedCallback adalah untuk integrasi platform langsung; PredictiveBackHandler hanya untuk animasi kemajuan Compose. Keadaan didayakan panggilan balik mengikut sama ada borang adalah kotor. Pratonton mengubah visual yang boleh berbalik, pembatalan memulihkannya, dan komit melakukan navigasi atau pengesahan.
"Saya akan mengelakkan panggilan balik keutamaan lalai atau tindanan yang menyekat animasi sistem dan memastikan animasi UI diasingkan daripada pengelogan. Aplikasi yang besar melancarkan enableOnBackInvokedCallback mengikut Activity, menguji Android 13, 14, dan 15 untuk komit dan pembatalan, serta membuang pemintasan onBackPressed dan KEYCODE_BACK secara beransur-ansur. Pemeriksaan penerimaan mengesahkan navigasi, pemulihan keadaan, susunan panggilan balik, dan tingkah laku kembali ke laman utama sistem, bukan hanya satu animasi."
Kesilapan lazim
- Kesilapan: menyemak keadaan borang kotor hanya di dalam
handleOnBackPressed→ Sebab ia gagal: pratonton telah pun berlaku dan pembatalan tidak dapat dipulihkan dengan betul → Pembetulan: dayakan atau lumpuhkan panggilan balik daripada keadaan yang boleh diperhatikan. - Kesilapan: mendaftarkan panggilan balik
PRIORITY_OVERLAYglobal di semua tempat → Sebab ia gagal: animasi prediktif sistem disekat → Pembetulan: gunakan hanya peristiwa UI yang diperlukan dan gunakan pemerhatian bukan menyekat untuk log. - Kesilapan: hanya memanggil
navigateBack()dalam Compose → Sebab ia gagal: keadaan pratonton kekal selepas pembatalan → Pembetulan: tangkap pembatalan dan pulihkan snapshot. - Kesilapan: hanya menguji pada peranti Android 15 → Sebab ia gagal: API keserasian dan tingkah laku lama kekal tidak disahkan → Pembetulan: rangkumi Android 13, 14, 15 dan bendera di peringkat aktiviti.
Soalan susulan dan respons
Apakah yang patut berlaku kepada data borang apabila pengguna melepaskan separuh jalan?
Pratonton hanya menukar visual sementara. Pastikan model borang dan data yang disimpan tidak berubah, kemudian pulihkan snapshot visual apabila gerak isyarat dibatalkan. Jangan paparkan dialog simpan/buang untuk gerak isyarat yang tidak pernah dikomitkan.
Mengapa tidak menggunakan satu panggilan balik global untuk setiap skrin?
Keutamaan panggilan balik bergantung pada susunan timbunan dan keadaan didayakan. Panggilan balik global boleh menyembunyikan logik Fragment, Navigation, atau Compose dan tidak dapat mengetahui keadaan skrin semasa yang belum disimpan. Panggilan balik tanggungjawab tunggal peringkat skrin lebih mudah disahkan.
Bagaimanakah anda mencatat log kembali tanpa mengorbankan animasi sistem?
Jangan gunakan panggilan balik lalai atau tindanan yang menyekat untuk tujuan pengelogan. Untuk meninggalkan Activity akar, gunakan pemerhati navigasi sistem atau isyarat kitaran hayat; pastikan panggilan balik UI hanya bertanggungjawab untuk tingkah laku UI.
Bagaimanakah aplikasi berbilang Activity yang besar melancarkan ciri ini?
Mulakan dengan tetapan aplikasi yang konservatif, kemudian ganti enableOnBackInvokedCallback=true pada Activity yang telah dihijrahkan. Kembangkan hanya selepas setiap Activity lulus ujian komit, pembatalan, panggilan balik bersarang, dan versi yang lebih lama.
API Compose manakah yang sesuai apabila hanya pemintasan akhir kembali diperlukan?
Gunakan BackHandler. Ia menyatakan pemintasan akhir dengan semantik pembatalan yang lebih mudah. Gunakan PredictiveBackHandler hanya apabila BackEventCompat.progress memacu animasi interaktif.
Rujukan
- Android Developers: Tambah sokongan untuk gerak isyarat predictive back.
- Android Developers: Reka bentuk predictive back.
- Android Developers: Mengenai Predictive back untuk Jetpack Compose.