Ang ActivityResultLauncher ay isang component ng Android Activity Result API, na ipinakilala sa bersyon Activity 1.2.0 ng androidx.activity library. Pinapalitan nito ang mga lumang pamamaraan na startActivityForResult at onActivityResult, na bahagi ng Android SDK mula noong paglikha nito. Ayon sa Android Developers (2024), inaalis ng bagong API ang mga problema ng mahigpit na pagkakabit sa Activity at kakulangan ng kaligtasan ng uri. ActivityResultLauncher ay nagrerehistro nang maaga at gumagamit ng Contract para sa mahigpit na pag-type ng input at output data.
Mga Pangunahing Punto
ActivityResultLauncher ay isang klase mula sa package na androidx.activity.result na nagbibigay ng mekanismong ligtas sa uri para sa paglunsad ng Activity at pagtanggap ng resulta. Ang Launcher ay nilikha sa pamamagitan ng pamamaraang registerForActivityResult, na tumatanggap ng dalawang parameter: Contract (naglalarawan ng input at output types) at ActivityResultCallback (tagaproseso ng resulta). Pagkatapos ng pagrehistro, ang launcher ay handa na para sa tawag sa pamamagitan ng pamamaraang launch.
Ang pangunahing pagkakaiba mula sa lumang API ay ang paghihiwalay ng pagrehistro at paglunsad. Ang pagrehistro ay ginagawa sa yugto ng pagsisimula (Activity.onCreate o Fragment.onCreate), ang callback ay nakakabit sa launcher nang isang beses at garantisadong mag-trigger kapag bumalik ang resulta. Ito ay nag-aalis ng problema kung saan ang onActivityResult ay nag-trigger sa hindi inaasahang pagkakasunod-sunod o sa isang nawasak na Activity.
Sinusuportahan ng ActivityResultLauncher ang lahat ng mga scenario na dati nang pinangasiwaan sa pamamagitan ng onActivityResult: paglunsad ng camera, gallery, paghingi ng mga contact, pahintulot, at custom na Activity. Bukod pa rito, ang API ay napapalawak: ang developer ay maaaring lumikha ng sariling Contract para sa mga tiyak na scenario ng pagpapalitan ng data sa pagitan ng mga Activity.
startActivityForResult ay bahagi ng Android SDK mula noong bersyon API Level 1 (2008) at nanatiling pangunahing paraan ng pagkuha ng resulta mula sa Activity nang higit sa 12 taon. Gayunpaman, ang pamamaraang ito ay may mga pangunahing kakulangan na inalis ng Google sa Activity Result API. Tingnan natin ang mga pangunahing problema at kung paano nilulutas ng bagong API ang mga ito.
Ang pamamaraang startActivityForResult ay nakakabit sa Activity at Fragment sa pamamagitan ng requestCode — isang arbitraryong integer na ipinapasa sa onActivityResult. Ang developer ay manu-manong nagtutugma ng code sa inilunsad na operasyon, na humantong sa mga pagkakamali sa muling paggamit ng code at pamana. Ganap na inaalis ng ActivityResultLauncher ang requestCode: ang callback ay nakakabit sa isang partikular na launcher sa yugto ng pagrehistro at tinatawag lamang para dito.
Sa mga pagbabago sa configuration (pag-ikot ng screen, pagbabago ng wika) ang Activity ay muling nilikha at ang onActivityResult ay maaaring hindi mag-trigger — nawala ang callback. Awtomatikong ini-save at ni-restore ng Activity Result API ang estado ng launcher sa pamamagitan ng SavedStateRegistry, na ginagarantiyang matatanggap ang resulta kahit na matapos ang muling paglikha ng Activity.
Ang lumang API ay nagpadala ng resulta sa pamamagitan ng Intent na may Bundle, kung saan ang mga susi at uri ng data ay hindi sinuri ng compiler. Ang Activity Result API ay gumagamit ng Contract — isang generic na interface na tumutukoy sa uri ng input data (I) at uri ng resulta (O). Ang mga pagkakamali sa hindi pagkakatugma ng uri ay natutukoy sa yugto ng compilation, hindi sa runtime.
| Katangian | startActivityForResult | ActivityResultLauncher |
|---|---|---|
| RequestCode | Nangangailangan ng manu-manong pamamahala | Awtomatiko, hindi kinakailangan |
| Kaligtasan ng uri | Wala | Generic Contract |
| Pag-save sa pag-ikot | Nawawala | SavedStateRegistry |
| Minimal na API | API Level 1 | Activity 1.2.0 |
| Paggamit sa Compose | Hindi sinusuportahan | rememberLauncherForActivityResult |
Contract ay isang interface na ActivityResultContract<I, O> na tumutukoy kung paano ilunsad ang Activity at kung paano bigyang-kahulugan ang resulta. Nagbibigay ang Google ng isang set ng mga built-in na kontrata para sa mga karaniwang scenario na sumasaklaw sa karamihan ng mga pangangailangan ng developer.
StartIntentSenderForResult ay ang pangunahing kontrata para sa paglunsad ng IntentSender. Ginagamit sa mga system scenario, halimbawa sa pag-authenticate sa pamamagitan ng Google Sign-In o pagbabayad sa pamamagitan ng Google Pay. Input parameter — PendingIntent, output — ActivityResult na may code at Intent.
RequestMultiplePermissions ay ang kontrata para sa paghingi ng maraming pahintulot nang sabay-sabay sa Android 6.0+. Input parameter — isang array ng String na may mga pangalan ng pahintulot, output — Map<String, Boolean> na may resulta ng bawat kahilingan. Dati ito ay nangangailangan ng manu-manong pag-parse sa onRequestPermissionsResult na may pagtutugma ng mga code ng kahilingan.
TakePicture ay ang kontrata para sa pagkuha ng larawan sa pamamagitan ng system camera. Input — Uri kung saan i-save ang larawan, output — Boolean (tagumpay). TakeVideo ay gumagana nang katulad sa video. Ang mga kontratang ito ay pumapalit sa lumang MediaStore.ACTION_IMAGE_CAPTURE na may hindi matatag na pag-uugali sa iba't ibang device.
GetContent ay ang kontrata para sa pagpili ng nilalaman sa pamamagitan ng system picker. Input — MIME type (halimbawa image/*), output — Uri ng napiling file. OpenDocument ay naiiba sa suporta para sa maramihang pagpili at pag-filter ayon sa mga uri ng dokumento. Ang parehong kontrata ay gumagana sa pamamagitan ng SAF (Storage Access Framework).
CreateDocument ay ang kontrata para sa paglikha ng bagong dokumento sa pamamagitan ng system dialog. Pinipili ng user ang pangalan at folder, ibinabalik ng system ang Uri para sa pagsulat. OpenDocumentTree ay nagbibigay ng access sa buong direktoryo — pinipili ng user ang isang folder, at ang application ay tumatanggap ng tree-uri para sa pagbabasa at pagsulat ng lahat ng file sa loob.
Ang pangunahing pattern ng paggamit ng ActivityResultLauncher sa klasikong Android ay binubuo ng dalawang hakbang: pagrehistro sa pamamagitan ng registerForActivityResult sa yugto ng pagsisimula at tawag na launch bilang tugon sa aksyon ng user. Tingnan natin ang isang tipikal na halimbawa ng pagpili ng larawan mula sa gallery.
Irehistro ang launcher sa onCreate ng Activity — ginagarantiyahan nito na ang callback ay handa bago ang anumang posibleng tawag. Huwag kailanman irehistro ang launcher kaagad bago ang paglunsad — ito ay lumalabag sa kontrata ng API at maaaring humantong sa pagkawala ng resulta sa muling paglikha ng Activity.
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/*")
}
}
Sa Fragment, ang pagrehistro ay ginagawa sa onCreate, onAttach o pagsisimula sa onCreateView. Ang FragmentActivity ay nagpapasa ng launcher sa pamamagitan ng parent na Activity, kaya ang resulta ay pinoproseso sa loob ng Fragment, hindi sa Activity. Ito ay nagpapabuti ng encapsulation kumpara sa onActivityResult, kung saan ang lahat ng resulta mula sa lahat ng Fragment ay nakolekta sa isang pamamaraan ng Activity.
class ProfileFragment : Fragment() {
private val cameraLauncher =
registerForActivityResult(ActivityResultContracts.TakePicture()) { success ->
if (success) { updateProfilePhoto() }
}
fun takePhoto(photoUri: Uri) {
cameraLauncher.launch(photoUri)
}
}
Jetpack Compose ay nagbibigay ng espesyal na composable functionality para sa Activity Result API — rememberLauncherForActivityResult. Hindi tulad ng klasikong approach, sa Compose ang launcher ay nilikha bilang isang object na nakakabit sa lifecycle ng composable sa pamamagitan ng remember. Ito ay nagpapahintulot sa paggamit ng Activity Result API sa ganap na deklaratibong estilo nang walang direktang access sa Activity o Fragment.
rememberLauncherForActivityResult ay tumatanggap ng Contract at callback, na nagbabalik ng ActivityResultLauncher. Ang launcher ay pinapanatili sa recomposition at awtomatikong nililinis kapag lumabas sa komposisyon. Ang tawag na launch ay nangyayari bilang tugon sa isang event — halimbawa, pagpindot ng button o pagbabago ng estado.
@Composable
fun PhotoPicker() {
val context = LocalContext.current
val launcher = rememberLauncherForActivityResult(
ActivityResultContracts.GetContent()
) { uri -> handleImage(uri) }
Button(onClick = { launcher.launch("image/*") }) {
Text("Pumili ng Larawan")
}
}
Paghingi ng pahintulot sa Compose ay ginagawa din sa pamamagitan ng rememberLauncherForActivityResult na may kontratang RequestPermission o RequestMultiplePermissions. Inirerekomenda ng Google ang paggamit ng accompanist-permissions, ngunit sa ilalim ng hood ay gumagamit din ito ng Activity Result API. Para sa pagkontrol ng estado ng pahintulot, maginhawang mag-imbak ng status sa remember o ViewModel.
Activity Result API ay inalis ang maraming problema ng lumang approach, ngunit ang hindi tamang paggamit nito ay maaaring humantong sa mga bagong uri ng pagkakamali. Tingnan natin ang mga pinakakaraniwang problema at paraan upang maiwasan ang mga ito.
Pagrehistro ng launcher ay dapat gawin sa pagsisimula ng component — sa onCreate ng Activity o initializer ng Fragment. Kung irehistro mo ang launcher sa loob ng lambda, callback o coroutine, sa muling paglikha ng Activity ang pagrehistro ay maaaring gawin muli, at ang lumang launcher ay mawawalan ng koneksyon sa resulta.
Bawat launcher ay tumatanggap ng natatanging susi para sa pag-save ng estado. Kung magrehistro ka ng dalawang launcher na may parehong Contract sa isang component, ang SavedStateRegistry ay maaaring mag-overwrite ng estado ng isa sa isa pa. Nagbabala ang Android Studio tungkol dito sa pamamagitan ng lint rule na UnnecessaryRegisterForActivityResult, ngunit mas mainam na kontrolin ang pagiging natatangi nang manu-mano.
Maaaring kanselahin ng user ang aksyon — pindutin ang system back button, i-minimize ang app, o lumipat sa ibang app. Sa kasong ito, ang callback ay makakatanggap ng null o ActivityResult na may RESULT_CANCELED. Palaging suriin ang resulta para sa null bago gamitin upang maiwasan ang NullPointerException.
Kung ang iyong app ay madalas na naglulunsad ng magkakatulad na scenario — halimbawa, pagpili ng contact na may pagbabalik ng pangalan at telepono — gumawa ng sarili mong Contract. Ito ay nagpapabuti sa pagiging nababasa ng code at nagpapahintulot sa sentralisadong pagbabago ng lohika ng paglunsad at pangangasiwa ng resulta.
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) }
}
Mga Madalas Itanong
Hindi — ang ActivityResultLauncher ay nangangailangan ng konteksto ng Activity o Fragment para sa pagrehistro. Gamitin ang ViewModel lamang para sa pag-imbak ng estado, at likhain ang launcher sa Activity o Fragment at ipasa ang resulta sa ViewModel.
Activity Result API ay available simula sa library na activity-ktx 1.2.0. Minimal na SDK — API Level 14 (Android 4.0), ngunit karamihan ng mga kontrata ay gumagana lamang sa API Level 19+.
Ang paulit-ulit na tawag ng launch bago makumpleto ang unang operasyon ay hindi papansinin. Ang Activity Result API ay hindi sumusuporta sa parallel na paglunsad — maghintay ng callback mula sa unang operasyon bago ang bagong tawag.
Ang migrasyon ay ginagawa sa pamamagitan ng pagpapalit ng tawag na startActivityForResult ng registerForActivityResult na may angkop na Contract. Alisin ang onActivityResult at pangasiwaan ang resulta sa callback ng launcher. Nagbibigay ang Google ng gabay sa migrasyon sa dokumentasyon ng Android Developers.
Oo, maraming library ang sumusuporta sa integrasyon sa pamamagitan ng ActivityResultContracts. Halimbawa, ang ML Kit Barcode Scanner ay gumagamit ng StartIntentSenderForResult para sa paglunsad ng scanner. Suriin ang dokumentasyon ng partikular na library.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din