Android進(jìn)階:全面擁抱Activity Results API來替代onActivityResult
本文轉(zhuǎn)載自微信公眾號「Android開發(fā)編程」,作者Android開發(fā)編程。轉(zhuǎn)載本文請聯(lián)系A(chǔ)ndroid開發(fā)編程代碼眾號。
前言
隨著應(yīng)用的擴展,onActivityResult回調(diào)方法各種嵌套、耦合嚴(yán)重、難以維護(hù);
在google最新的activity-ktx beta版本中已經(jīng)廢棄了原onActivityResult方法,推薦使用Activity Results API來處理頁面數(shù)據(jù)的處理;
通過新的 Activity Result API,我們可以單獨的類中處理結(jié)果回調(diào),真正做到單一職責(zé)。
今天我們就來介紹下:
一、activity results api介紹和使用方法
1、什么是results api
Activity Results API 是 Google官方推薦的Activity、Fragment獲取返回結(jié)果的方式。ActivityResultContract是一個抽象類,也是我們需要定義的協(xié)議,它需要去定義如何傳遞數(shù)據(jù)和如何處理返回的數(shù)據(jù);
相當(dāng)于原startActivityForResult 和onActivityResult方法;
2、使用步驟
主要用到兩個組件
- ActivityResultContract: 協(xié)議,它定義了如何傳遞數(shù)據(jù)和如何處理返回的數(shù)據(jù);
- ActivityResultLauncher: 啟動器,調(diào)用ActivityResultLauncher的launch方法來啟動頁面跳轉(zhuǎn),作用相當(dāng)于原來的startActivity()。
2.1在app下的build.gradle中加入依賴
- mplementation 'androidx.activity:activity-ktx:1.2.0-beta01'
- implementation 'androidx.fragment:fragment-ktx:1.3.0-beta01'
2.2首先自定義一個ActivityResultContract,實現(xiàn)兩個activity互傳的數(shù)據(jù)處理
- class MyActivityResultContract : ActivityResultContract<String, String?>() {
- override fun createIntent(context: Context, input: String?): Intent {
- return Intent(context, SecondActivity::class.java).apply {
- putExtra("input", input)
- }
- }
- override fun parseResult(resultCode: Int, intent: Intent?): String? {
- val data = intent?.getStringExtra("result")
- return if (resultCode == Activity.RESULT_OK && !TextUtils.isEmpty(data)) data else null
- }
- }
- 調(diào)用registerForActivityResult方法,注冊剛剛定義的contract協(xié)議,返回一個activityResultLauncher對象。
- val activityResultLauncher = registerForActivityResult(MyActivityResultContract()) {
- Toast.makeText(this, "result value is :${it}", Toast.LENGTH_LONG).show()
- }
2.3 用返回的launcher對象啟動另一個activity界面
- btn_start_second.setOnClickListener {
- activityResultLauncher.launch("second activity start")
- }
3、使用內(nèi)置的 ActivityResultContract來進(jìn)行頁面跳轉(zhuǎn)
還可以通過ActivityResultContracts類來調(diào)用谷歌為我們內(nèi)置的Contract,其中包含來各種常用的Contract
- @StartActivityForResult: 通用的Contract,不做任何轉(zhuǎn)換,Intent作為輸入,ActivityResult作為輸出,這也是最常用的一個協(xié)定;
- @RequestMultiplePermissions:用于請求一組權(quán)限;
- @RequestPermission: 用于請求單個權(quán)限;
- @TakePicturePreview: 調(diào)用MediaStore.ACTION_IMAGE_CAPTURE拍照,返回值為Bitmap圖片
- @TakePicture: 調(diào)用MediaStore.ACTION_IMAGE_CAPTURE拍照,并將圖片保存到給定的Uri地址,返回true表示保存成功;
- @TakeVideo: 調(diào)用MediaStore.ACTION_VIDEO_CAPTURE 拍攝視頻,保存到給定的Uri地址,返回一張縮略圖;
- @PickContact: 從通訊錄APP獲取聯(lián)系人;
- @GetContent: 提示用選擇一條內(nèi)容,返回一個通過ContentResolver#openInputStream(Uri)訪問原生數(shù)據(jù)的Uri地址(content://形式) 。默認(rèn)情況下,它增加了Intent#CATEGORY_OPENABLE, 返回可以表示流的內(nèi)容;
- @CreateDocument: 提示用戶選擇一個文檔,返回一個(file:/http:/content:)開頭的Uri。
- @OpenMultipleDocuments: 提示用戶選擇文檔(可以選擇多個),分別返回它們的Uri,以List的形式;
- @OpenDocumentTree: 提示用戶選擇一個目錄,并返回用戶選擇的作為一個Uri返回,應(yīng)用程序可以完全管理返回目錄中的文檔;
- private val activityResultLauncher =
- registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
- if (it.resultCode == RESULT_OK) {
- val result = intent?.getStringExtra("result")
- tvName.text = result
- }
- }
- btnStartSecond.setOnClickListener {
- //點擊跳轉(zhuǎn)到SecondActivity
- val intent = Intent(this, SecondActivity::class.java)
- intent.putExtra("name", "我是第一個頁面?zhèn)鬟^去的參數(shù)")
- activityResultLauncher.launch(intent)
- }
使用系統(tǒng)內(nèi)置的ActivityResultContract可以很方便的實現(xiàn)頁面間傳值來。
總結(jié)
使用activity results api替代傳統(tǒng)的onActivityResult方法,可以簡化我們的代碼,提高代碼的重用性;一起加油!