關注個人公衆號 「安安安安卓」 學習更多知識java
很簡單的一句話,ActivityResultContract
是用來在大部分場景中對startActivityForResult
和onActivityResult
進行替代的官方api
。api
ActivityResultContract
提供了一種類型安全的獲取返回值的方式,好比拍照的api會返回泛型指定的bitmap。這避免了咱們手動處理onActivityResult回調致使的各類問題。瀏覽器
固然了我認爲ActivityResultContract
最好的地方就是省心,尤爲對於系統預置的集中ActivityResultContract
,只須要兩步模板代碼便可實現功能。安全
要實現自定義行爲須要先自定義一個ActivityResultContract
類,定義以下:markdown
ActivityResultContract
類中有兩個泛型,第一個泛型是I,第二個泛型是O,I表示輸入也就是咱們啓動activity須要putExtra的內容,O表述輸入即onActivityResult返回的數據app
ActivityResultContract
有兩個方法ide
createIntent
表示建立啓動activity
的Intent
,其中方法的第二個參數可用於傳給待啓動activity
的參數parseResult
表示對返回數據的解析,方法的返回值就是registerForActivityResult
中回調的數據class CustomResultContracts : ActivityResultContract<Int, String>() {
override fun createIntent(context: Context, input: Int?): Intent {
return Intent(context, DestinishActivity::class.java).putExtra("input",input)
}
override fun parseResult(resultCode: Int, intent: Intent?): String {
return intent?.getStringExtra("data") ?: "未返回數據"
}
}
複製代碼
private val customContract = registerForActivityResult(CustomResultContracts()){
getData(14).content="自定義Contracts返回數據:$it"
getData(14).notifyDataSetChange()
}
複製代碼
customContract.launch(1)
複製代碼
本例調用方法後會啓動一個activity,新的activity點擊返回數據將數據返回到列表中展現學習
註冊代碼
this
//註冊結果監聽
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == 3) {
showResult(it.data?.getStringExtra("data"))
}
}
複製代碼
啓動代碼
spa
//啓動activity,參數傳intent
startForResult.launch(Intent(this@MainActivity, DestinishActivity::class.java))
複製代碼
跳轉到拍照頁面,拍攝的照片會被保存到圖庫中
registerForActivityResult(ActivityResultContracts.TakePicturePreview()) {
getData(1).let {
it.notifyDataSetChange()
}
}
複製代碼
模擬器錄製不變,暫無效果圖
TakePicture
方法會跳轉到系統相機拍攝一張照片,返回bitmap,可是不會把圖片保存到圖庫
private val takePreviewPic = registerForActivityResult(ActivityResultContracts.TakePicture()) {
logEE("搞預覽圖片成功")
}
複製代碼
拍攝代碼,須要說明的是拍攝視頻完成後會須要等待較長時間,等待手機處理完視頻的存儲
private val captureVideo = registerForActivityResult(ActivityResultContracts.CaptureVideo()) {
logEE("拍攝視頻成功:$it")
}
複製代碼
模擬器錄製不變,暫無效果圖
很是簡潔的方式實現權限申請
cameraPermission.launch(Manifest.permission.CAMERA)
複製代碼
private val cameraPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
getData(3).apply {
content = "請求相機權限結果$it"
notifyDataSetChange()
}
}
複製代碼
mutlePermission.launch(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
)
複製代碼
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
var result = ""
it.forEach { gaint ->
result += "獲取${gaint.key} 權限 ${if (gaint.value) "成功" else "失敗"}"
}
getData(4).content = result
getData(4).notifyDataSetChange()
}
複製代碼
pickContact.launch(null)//參數傳空
複製代碼
private val pickContact = registerForActivityResult(ActivityResultContracts.PickContact()) {
logEE(it.toString())
getData(8).apply {
content = it.toString()
notifyDataSetChange()
}
}
複製代碼
實現使用文件瀏覽器選擇圖片功能
getContent.launch("image/*")
複製代碼
private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) {
logEE(it.toString())
}
複製代碼
由於模擬器沒有圖片可選,因此沒有內容展現
2021/08/06 更新新內容以下
Fragment
中的使用和activity中是同樣的,直接放參考代碼吧
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<Button>(R.id.btn).setOnClickListener {
request.launch(Intent(activity, DestinishActivity::class.java))//啓動新activity
}
}
/** * 註冊結果監聽 */
val request = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
logEE(it.data?.getStringExtra("data")!!)
}
複製代碼
最終效果和activity是一致的