ActivityResultLauncher — Android Activity Result API-nin komponentidir, androidx.activity kitabxanasının Activity 1.2.0 versiyasında təqdim edilmişdir. Android SDK-nın yarandığı andan etibarən onun hissəsi olan köhnəlmiş startActivityForResult və onActivityResult metodlarını əvəz edir. Android Developers (2024)-ə görə, yeni API Activity ilə sərt əlaqə və tip təhlükəsizliyinin olmaması problemlərini aradan qaldırır. ActivityResultLauncher əvvəlcədən qeydiyyatdan keçir və giriş və çıxış məlumatlarının ciddi tipləşdirilməsi üçün Contract istifadə edir.
Əsas məqamlar
ActivityResultLauncher — androidx.activity.result paketindən olan sinifdir, Activity-ni işə salmaq və nəticə almaq üçün tip təhlükəsiz mexanizm təqdim edir. Launcher iki parametr qəbul edən registerForActivityResult metodu vasitəsilə yaradılır: Contract (giriş və çıxış tiplərini təsvir edir) və ActivityResultCallback (nəticə emalçısı). Qeydiyyatdan sonra launcher launch metodu vasitəsilə çağırışa hazırdır.
Köhnə API-dən əsas fərq — qeydiyyat və işə salmanın ayrılmasıdır. Qeydiyyat inisiallaşdırma mərhələsində (Activity.onCreate və ya Fragment.onCreate) həyata keçirilir, callback launcher ilə bir dəfə əlaqələndirilir və nəticə qayıtdıqda zəmanətli işə düşür. Bu, onActivityResult-un gözlənilməz ardıcıllıqda və ya məhv edilmiş Activity-də işə düşməsi problemini aradan qaldırır.
ActivityResultLauncher bütün ssenariləri dəstəkləyir ki, bunlar da əvvəllər onActivityResult vasitəsilə emal olunurdu: kamera işə salma, qalereya, kontakt sorğusu, icazələr və fərdi Activity-lər. Bundan əlavə, API genişləndirilə biləndir: tərtibatçı Activity-lər arasında məlumat mübadiləsinin spesifik ssenariləri üçün öz Contract-larını yarada bilər.
startActivityForResult Android SDK-nın API Level 1 (2008) versiyasından etibarən onun hissəsi idi və 12 ildən çox müddət ərzində Activity-dən nəticə almağın əsas yolu olaraq qaldı. Lakin bu metodun Activity Result API-də Google-un aradan qaldırdığı fundamental çatışmazlıqları var idi. Əsas problemlərə və yeni API-nin onları necə həll etdiyinə baxaq.
startActivityForResult metodu Activity və Fragment ilə requestCode vasitəsilə əlaqələndirilir — onActivityResult-a ötürülən ixtiyari tam ədəd. Tərtibatçı kodu işə salınmış əməliyyatla əl ilə uyğunlaşdırırdı, bu da kodun təkrar istifadəsi və vərəsəlik zamanı səhvlərə səbəb olurdu. ActivityResultLauncher requestCode-u tamamilə aradan qaldırır: callback qeydiyyat mərhələsində konkret launcher ilə əlaqələndirilir və yalnız onun üçün çağırılır.
Konfiqurasiya dəyişiklikləri zamanı (ekranın döndərilməsi, dilin dəyişməsi) Activity yenidən yaradılırdı və onActivityResult işə düşməyə bilərdi — callback itirdi. Activity Result API SavedStateRegistry vasitəsilə launcher vəziyyətini avtomatik saxlayır və bərpa edir, bu da Activity-nin yenidən yaradılmasından sonra belə nəticənin alınmasını təmin edir.
Köhnə API nəticəni Bundle ilə Intent vasitəsilə ötürürdü, burada açarlar və məlumat tipləri kompilyator tərəfindən yoxlanılmırdı. Activity Result API Contract — giriş məlumatlarının tipini (I) və nəticə tipini (O) təyin edən generic interfeys istifadə edir. Tip uyğunsuzluğu səhvləri runtime-da deyil, kompilyasiya mərhələsində aşkar edilir.
| Xüsusiyyət | startActivityForResult | ActivityResultLauncher |
|---|---|---|
| RequestCode | Əl ilə idarə tələb olunur | Avtomatik, tələb olunmur |
| Tip təhlükəsizliyi | Yox | Generic Contract |
| Döndərmədə saxlanma | İtirilir | SavedStateRegistry |
| Minimal API | API Level 1 | Activity 1.2.0 |
| Compose-da istifadə | Dəstəklənmir | rememberLauncherForActivityResult |
Contract — ActivityResultContract<I, O> interfeysidir, Activity-ni necə işə salmağı və nəticəni necə interpretasiya etməyi təyin edir. Google tərtibatçının əksər ehtiyaclarını əhatə edən tipik ssenarilər üçün daxili kontraktlar dəsti təqdim edir.
StartIntentSenderForResult — IntentSender-i işə salmaq üçün əsas kontrakt. Sistem ssenarilərində, məsələn Google Sign-In vasitəsilə autorizasiya və ya Google Pay ilə ödəniş zamanı istifadə olunur. Giriş parametri — PendingIntent, çıxış — kod və Intent ilə ActivityResult.
RequestMultiplePermissions — Android 6.0+-da eyni anda bir neçə icazə tələb etmək üçün kontrakt. Giriş parametri — icazə adları ilə String massivi, çıxış — hər sorğunun nəticəsi ilə Map<String, Boolean>. Əvvəllər bu, sorğu kodlarının uyğunlaşdırılması ilə onRequestPermissionsResult-da əl ilə təhlil tələb edirdi.
TakePicture — sistem kamerası vasitəsilə şəkil çəkmək üçün kontrakt. Giriş — şəklin saxlanacağı Uri, çıxış — Boolean (uğur). TakeVideo eyni şəkildə video ilə işləyir. Bu kontraktlar müxtəlif cihazlarda qeyri-sabit davranışı olan köhnəlmiş MediaStore.ACTION_IMAGE_CAPTURE-ni əvəz edir.
GetContent — sistem picker vasitəsilə məzmun seçmək üçün kontrakt. Giriş — MIME tipi (məsələn image/*), çıxış — seçilmiş faylın Uri-si. OpenDocument çoxsaylı seçim dəstəyi və sənəd tipləri üzrə filtrləmə ilə fərqlənir. Hər iki kontrakt SAF (Storage Access Framework) vasitəsilə işləyir.
CreateDocument — sistem dialoq pəncərəsi vasitəsilə yeni sənəd yaratmaq üçün kontrakt. İstifadəçi ad və qovluq seçir, sistem yazmaq üçün Uri qaytarır. OpenDocumentTree bütün kataloqa giriş verir — istifadəçi qovluq seçir və tətbiq daxilindəki bütün faylları oxumaq və yazmaq üçün tree-uri alır.
Klassik Android-də ActivityResultLauncher istifadəsinin əsas nümunəsi iki addımdan ibarətdir: inisiallaşdırma mərhələsində registerForActivityResult vasitəsilə qeydiyyat və istifadəçinin hərəkətinə cavab olaraq launch çağırışı. Qalereyadan şəkil seçiminin tipik nümunəsinə baxaq.
Launcher-i Activity-nin onCreate-də qeydiyyatdan keçirin — bu, callback-in hər hansı mümkün çağırışdan əvvəl hazır olmasını təmin edir. Heç vaxt launcher-i birbaşa işə salmadan əvvəl qeydiyyatdan keçirməyin — bu, API kontraktını pozur və Activity-nin yenidən yaradılması zamanı nəticənin itirilməsinə səbəb ola bilər.
class MainActivity : AppCompatActivity() {
private val pickImageLauncher =
registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
uri?.let { binding.imageView.setImageURI(it) }
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
pickImageLauncher.launch("image/*")
}
}
Fragment-də qeydiyyat onCreate, onAttach və ya onCreateView-də inisiallaşdırmada həyata keçirilir. FragmentActivity launcher-i valideyn Activity vasitəsilə ötürür, buna görə də nəticə Activity-də deyil, Fragment daxilində emal olunur. Bu, onActivityResult ilə müqayisədə enkapsulyasiyanı yaxşılaşdırır, burada bütün Fragment-lərdən bütün nəticələr Activity-nin bir metodunda toplanırdı.
class ProfileFragment : Fragment() {
private val cameraLauncher =
registerForActivityResult(ActivityResultContracts.TakePicture()) { success ->
if (success) { updateProfilePhoto() }
}
fun takePhoto(photoUri: Uri) {
cameraLauncher.launch(photoUri)
}
}
Jetpack Compose Activity Result API üçün xüsusi composable funksionallığı təqdim edir — rememberLauncherForActivityResult. Klassik yanaşmadan fərqli olaraq, Compose-da launcher remember vasitəsilə composable həyat dövrünə bağlanmış obyekt kimi yaradılır. Bu, Activity və ya Fragment-ə birbaşa giriş olmadan Activity Result API-dən tam deklarativ üslubda istifadə etməyə imkan verir.
rememberLauncherForActivityResult Contract və callback qəbul edir, ActivityResultLauncher qaytarır. Launcher rekompozisiya zamanı saxlanılır və kompozisiyadan çıxışda avtomatik təmizlənir. launch çağırışı hadisəyə cavab olaraq baş verir — məsələn, düymənin kliklənməsi və ya vəziyyətin dəyişməsi.
@Composable
fun PhotoPicker() {
val context = LocalContext.current
val launcher = rememberLauncherForActivityResult(
ActivityResultContracts.GetContent()
) { uri -> handleImage(uri) }
Button(onClick = { launcher.launch("image/*") }) {
Text("Şəkil seç")
}
}
Compose-da icazələrin tələbi də RequestPermission və ya RequestMultiplePermissions kontraktı ilə rememberLauncherForActivityResult vasitəsilə həyata keçirilir. Google accompanist-permissions istifadə etməyi tövsiyə edir, lakin o da daxili olaraq Activity Result API-dən istifadə edir. İcazə vəziyyətinə nəzarət üçün statusu remember və ya ViewModel-də saxlamaq rahatdır.
Activity Result API köhnə yanaşmanın bir çox problemlərini aradan qaldırdı, lakin onun düzgün istifadə edilməməsi yeni növ səhvlərə səbəb ola bilər. Ən çox yayılmış problemlərə və onlardan qaçma yollarına baxaq.
Launcher-in qeydiyyatı komponentin inisiallaşdırılması zamanı — Activity-nin onCreate-də və ya Fragment-in inisiallaşdırıcısında aparılmalıdır. Əgər launcher-i lambda, callback və ya korutin daxilində qeydiyyatdan keçirsəniz, Activity yenidən yaradıldıqda qeydiyyat təkrar edilə bilər və köhnə launcher nəticə ilə əlaqəsini itirər.
Hər launcher vəziyyəti saxlamaq üçün unikal açar alır. Bir komponentdə eyni Contract ilə iki launcher qeydiyyatdan keçirsəniz, SavedStateRegistry birinin vəziyyətini digərinin üzərinə yaza bilər. Android Studio bu barədə UnnecessaryRegisterForActivityResult lint qaydası ilə xəbərdarlıq edir, lakin unikallığı əl ilə idarə etmək daha yaxşıdır.
İstifadəçi əməliyyatı ləğv edə bilər — sistemin geri düyməsini basa, tətbiqi kiçildə və ya başqa tətbiqə keçə bilər. Bu halda callback null və ya RESULT_CANCELED ilə ActivityResult alacaq. NullPointerException-dan qaçmaq üçün istifadədən əvvəl nəticəni həmişə null olub-olmadığını yoxlayın.
Əgər tətbiqiniz tez-tez eyni tipli ssenariləri işə salırsa — məsələn, ad və telefon qaytaran kontakt seçimi — öz Contract-ınızı yaradın. Bu, kodun oxunaqlılığını yaxşılaşdırır və işə salma və nəticənin emalı məntiqini mərkəzləşdirilmiş şəkildə dəyişməyə imkan verir.
class PickContactContract : ActivityResultContract<Void, ContactData?>() {
override fun createIntent(context: Context, input: Void?) =
Intent(Intent.ACTION_PICK).setType(ContactsContract.Contacts.CONTENT_TYPE)
override fun parseResult(resultCode: Int, intent: Intent?) =
intent?.data?.let { queryContact(it) }
}
Tez-tez verilən suallar
Xeyr — ActivityResultLauncher qeydiyyat üçün Activity və ya Fragment konteksti tələb edir. ViewModel-dən yalnız vəziyyəti saxlamaq üçün istifadə edin, launcher-i isə Activity və ya Fragment-də yaradın və nəticəni ViewModel-ə ötürün.
Activity Result API activity-ktx 1.2.0 kitabxanasından etibarən mövcuddur. Minimal SDK — API Level 14 (Android 4.0), lakin əksər kontraktlar yalnız API Level 19+-da işləyir.
Təkrar launch çağırışı birinci əməliyyat tamamlanana qədər nəzərə alınmayacaq. Activity Result API paralel işə salmaları dəstəkləmir — yeni çağırışdan əvvəl birinci əməliyyatdan callback gözləyin.
Miqrasiya startActivityForResult çağırışının müvafiq Contract ilə registerForActivityResult ilə əvəz edilməsi ilə həyata keçirilir. onActivityResult-u silin və nəticəni launcher callback-də emal edin. Google Android Developers sənədlərində miqrasiya təlimatı təqdim edir.
Bəli, bir çox kitabxana ActivityResultContracts vasitəsilə inteqrasiyanı dəstəkləyir. Məsələn, ML Kit Barcode Scanner skaneri işə salmaq üçün StartIntentSenderForResult istifadə edir. Xüsusi kitabxananın sənədlərini yoxlayın.
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