Back Press Handling — Android-də sistem “Geri” düyməsinin tutulması və işlənməsi mexanizmi olub, onun basılması zamanı hansı hərəkətin yerinə yetiriləcəyini müəyyən edir. Android Developers (2024) məlumatına görə, Android 11-dən başlayaraq ənənəvi onBackPressed() metodu OnBackPressedDispatcher ilə əvəz olunub. Yeni API komponentlərə iyerarxiyanın istənilən səviyyəsində basmanı tutmağa imkan verir, təkcə Activity deyil. Əsas fərq — prioritetlərlə zəncirdə çoxsaylı callback-lərin dəstəklənməsi.
Əsas məqamlar
Back Press Handling — Android-in sistem mexanizmidir ki, istifadəçi hardware və ya proqram “Geri” düyməsini basdıqda nə baş verdiyini müəyyən edir. Kontekstdən asılı olaraq basma: cari ekranı bağlayıb əvvəlkiyə qayıda bilər, klaviaturanı gizlədə bilər, Drawer və ya Bottom Sheet-i bağlaya bilər, istifadəçi kök ekrandadırsa tətbiqdən çıxa bilər.
“Geri” düyməsinin davranışı Android-in hər versiyası ilə təkamül etmişdir. Android 10-da naviqasiya jestləri meydana çıxdı, Android 11-də — OnBackPressedDispatcher standart API olaraq, Android 13-də isə təkmilləşdirilmiş predictive back gesture dəstəyi, burada sistem hərəkətin faktiki yerinə yetirilməsindən əvvəl keçid animasiyasını göstərir. Google ardıcıl olaraq bütün cihazlarda Back Press-in proqnozlaşdırıla bilən və ardıcıl davranışına doğru hərəkət edir.
“Geri” düyməsinin düzgün işlənməsi — Android tətbiqində UX-in kritik elementidir. İstifadəçi gözləyir ki, “Geri” basması onu naviqasiya yığınında əvvəlki ekrana qaytarsın, tətbiqi gözlənilmədən bağlamasın. Bu gözləntinin pozulması Google Play-də mənfi rəylərin və aşağı reytinqlərin əsas səbəblərindən biridir.
Back Press API-nin tarixi Android-də platformanın ümumi təkamülünü əks etdirir: Activity-də sadə metoddan lifecycle və Compose dəstəyi ilə çevik callback sisteminə qədər. Gəlin üç inkişaf mərhələsinə baxaq.
İlk Android API-dən etibarən “Geri” düyməsi Activity sinfinin onBackPressed metodunda işlənirdi. Tərtibatçı bu metodu override edir və öz məntiqini yazırdı. Problem onda idi ki, Fragment və View basmanı tuta bilmirdi — bütün idarəetmə Activity vasitəsilə gedirdi. Bu, şişmiş Activity-lərə və basmanı kimin işləməli olduğunu müəyyən etmək üçün mürəkkəb if-else zəncirinə gətirib çıxarırdı.
Activity 1.0.0 (AndroidX) ilə Google OnBackPressedDispatcher-i təqdim etdi. Bu, istənilən komponentdən — Activity, Fragment, Dialog, fərdi View-dən callback qəbul edən mərkəzi dispetçerdir. Callback-lər priority vasitəsilə sıra göstərilməklə qeydiyyatdan keçirilir və dinamik olaraq əlavə edilə və ya silinə bilər. OnBackPressedDispatcher köhnə onBackPressed-dən daha əvvəl çağırılır ki, bu da basmanı Activity-nin işləməsindən əvvəl tutmağa imkan verir.
Android 13 predictive back gesture-i təqdim etdi — istifadəçi jesti tamamlamamış “Geri” basmasının hara aparacağını göstərən sistem animasiyası. Bu animasiyanı dəstəkləmək üçün tərtibatçılar OnBackPressedDispatcher-dən istifadə etməli və isEnabled xassəsi vasitəsilə callback-in sistem animasiyasını dəstəklədiyini göstərməlidirlər. Callback predictive animation-ı dəstəkləmirsə, sistem tətbiq kontekstinə uyğun olmayan standart animasiyanı göstərir.
| API | Minimum SDK | Fragment dəstəyi | Predictive Back |
|---|---|---|---|
| onBackPressed | API Level 1 | Activity vasitəsilə | Yox |
| OnBackPressedDispatcher | Activity 1.0.0 | Birbaşa | Qismən |
| OnBackPressedDispatcher + lifecycle | Activity 1.3.0 | Lifecycle-aware | Tam |
OnBackPressedDispatcher — yeni Back Press API-nin özəyidir. O, callback zəncirini idarə edir, hadisəni işləyən ilk callback-ə qədər onları ardıcıl çağırır. Heç bir callback basmanı işləməzsə, dispetçer standart hərəkəti yerinə yetirir — Activity üçün finish() və ya Navigation Component üçün popBackStack().
Callback addCallback vasitəsilə LifecycleOwner və OnBackPressedCallback obyekti göstərilməklə qeydiyyatdan keçirilir. Callback isEnabled xassəsini ehtiva edir — false olarsa, callback buraxılır. priority üçün 0 (ən aşağı) ilə Integer.MAX_VALUE arasında dəyər ötürülə bilər. Fragment Activity Result API bu mexanizmdən həyat dövrünə bağlı callback-lərin avtomatik qeydiyyatı üçün istifadə edir.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val callback = object : OnBackPressedCallback(enabled = true) {
override fun handleOnBackPressed() {
if (isDrawerOpen) { closeDrawer() }
else { isEnabled = false; onBackPressed() }
}
}
onBackPressedDispatcher.addCallback(this, callback)
}
Callback avtomatik silinir, LifecycleOwner DESTROYED vəziyyətinə keçdikdə. Bu, ekranın fırlanması zamanı callback sızmalarının köhnə problemini həll edir. Callback Fragment-ə əlavə olunubsa, Fragment məhv edildikdə silinəcəyinə zəmanət verilir. Callback-in müvəqqəti söndürülməsi üçün isEnabled xassəsindən istifadə olunur — silmədən və yenidən qeydiyyatdan keçirmədən dəyişmək olar.
Çağırış sırası əlavə edilmə sırasının tərsidir: ən son əlavə edilən callback ilk növbədə idarəetməni alır. Bu məntiqlidir, çünki ən iç-içə olan UI elementi (məsələn, Fragment daxilində Bottom Sheet) basmanı valideyn Fragment-dən əvvəl işləməlidir. Ən dərin callback basmanı işləmirsə (isEnabled = false), idarəetmə zəncirdə növbətiyə ötürülür.
Fragment API requireActivity().onBackPressedDispatcher metodu vasitəsilə OnBackPressedDispatcher ilə öz inteqrasiyasını təmin edir. Fragment 1.2.0-dan başlayaraq, hər bir Fragment öz callback-ni qeydiyyatdan keçirə bilər ki, bu da avtomatik olaraq Fragment-in həyat dövrünə bağlanır və məhv edildikdə silinir.
Fragment-də callback-in qeydiyyatı onCreate, onViewCreated və ya hətta View-in özündə aparılır — yalnız LifecycleOwner-in (Fragment) aktiv olması vacibdir. Fragment STARTED vəziyyətinə keçdikdə callback işə düşür, STOPPED-da sönür. Bu, gizli Fragment-in (ViewPager-da) “Geri” basmasını işləməyəcəyinə zəmanət verir.
class EditorFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
showDiscardDialog()
}
}
requireActivity().onBackPressedDispatcher.addCallback(this, callback)
}
}
Dialoqlar və BottomSheet bağlanmaq üçün “Geri” basmasını avtomatik tutur. Bağlanmadan əvvəl əlavə hərəkət etmək lazımdırsa — daha yüksək prioritetlə callback qeydiyyatdan keçirin. Vacibdir: Dialog-da setCancelable(false) təyin etsəniz, callback işləməyəcək — bu sistem davranışıdır.
Jetpack Compose BackHandler composable funksiyası vasitəsilə “Geri” düyməsinin işlənməsi üçün deklarativ API təmin edir. BackHandler enabled (bool dəyəri) və onBack — basma zamanı çağırılan callback qəbul edir. enabled = false olarsa, basma zəncirlə daha irəli ötürülür.
BackHandler avtomatik olaraq valideyn Activity-nin OnBackPressedDispatcher-də OnBackPressedCallback qeydiyyatdan keçirir. O, composable-in həyat dövrünü nəzərə alır: kompozisiyadan çıxdıqda callback silinir. enabled vəziyyətə bağlana bilər — məsələn, təsdiq dialoqunu yalnız formada saxlanmamış dəyişikliklər olduqda göstərmək.
@Composable
fun EditScreen(hasUnsavedChanges: Boolean) {
BackHandler(enabled = hasUnsavedChanges) {
// Təsdiq dialoqunu göstər
}
Column {
TextField(value = ..., onValueChange = ...)
}
}
Predictive back gesture Compose-da Compose 1.5.0-dan dəstəklənir. BackHandler cihazda aktiv olduqda sistem keçid animasiyasını avtomatik idarə edir. Fərdi predictive-animasiya üçün 0-dan 1-ə qədər jestin gedişatını qaytaran predictiveBackHandler modifikatorundan istifadə edin.
Back Press Handling sadə görünür, amma praktikada tərtibatçılar bir sıra sistematik səhvlərə yol verirlər. Google tövsiyələri və icma təcrübəsi əsasında ən çox yayılmış problemlərə və onların həll yollarına baxaq.
Birbaşa finish() çağırışı handleOnBackPressed-də naviqasiya yığınında fon ekranları varsa, tətbiqdən gözlənilmədən çıxmağa səbəb ola bilər. Activity-ni bağlamadan əvvəl həmişə Navigation Component və ya Coordinator vasitəsilə NavController.backStack-i yoxlayın.
Callback-i LifecycleOwner olmadan (parametrsiz köhnə addCallback istifadə edərək) qeydiyyatdan keçirsəniz, callback əbədi yaşayacaq və Activity artıq məhv edilibsə NullPointerException yarada bilər. Həmişə LifecycleOwner ilə addCallback(this, callback) istifadə edin.
Modal pəncərələr (Bottom Sheet, Dialog) üçün həmişə isEnabled = true yalnız pəncərə görünəndə təyin edin. Pəncərənin vəziyyətini yoxlayan lambda ilə addCallback istifadə edin. Navigation Component NavHost üçün bunu avtomatik idarə edir.
Sürətli ikiqat “Geri” basması ikiqat finish() çağırışına səbəb ola bilər. 500 ms ərzində təkrar çağırışlardan qorunmaq üçün flag və ya throttleLast istifadə edin. Navigation Component bu vəziyyəti daxili olaraq idarə edir, lakin fərdi ssenarilərdə qorumanı əl ilə tətbiq etmək lazımdır.
private var lastBackPressTime = 0L
override fun handleOnBackPressed() {
val currentTime = System.currentTimeMillis()
if (currentTime - lastBackPressTime > 500) {
lastBackPressTime = currentTime
navigateBack()
}
}
Tez-tez verilən suallar
onBackPressed Android 11-də köhnəlmiş elan edildi, çünki o, yalnız Activity səviyyəsində işləyir. OnBackPressedDispatcher istənilən komponentə (Fragment, Dialog, View) həyat dövrü dəstəyi ilə vahid mexanizm vasitəsilə basmanı tutmağa imkan verir.
Android sistemi kənardan sürüşdürmə jestini tətbiq onu almamış sistem “Geri” basmasına çevirir. OnBackPressedDispatcher səviyyəsində bu iki hadisəni ayırd edə bilməzsiniz — hər ikisi handleOnBackPressed kimi gəlir.
Bəli, OnBackPressedDispatcher-in işlənməsi üç düyməli və jest naviqasiyası olan cihazlar üçün eynidir. Tutma kodu naviqasiya növündən asılı deyil — sistem özü jesti dispetçer çağırışına çevirir.
Aktiv edin Android 13+ emulyatorunun Developer Options-da predictive back. ADB istifadə edin: `adb shell settings put global enable_back_animation 1`. Aktiv etdikdən sonra sistem animasiyası “Geri” basdıqda keçidin ön izləməsini göstərəcək.
İki şərti yoxlayın: LifecycleOwner STARTED və ya RESUMED vəziyyətində olmalıdır və callback-in isEnabled-i true olmalıdır. Hər iki şərt yerinə yetirilirsə, callback-in düzgün OnBackPressedDispatcher-ə əlavə olunduğuna əmin olun — Fragment-də requireActivity().onBackPressedDispatcher istifadə edin.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun