Many developers have onActivityResult
complained for a long time: the need to define resultCode
and requestCode
, the use is cumbersome and error-prone. Now the newly released KTX ActivityResultContract
can solve the above troubles a lot
Basic use
Before
Traditional onActivityResult
writing
class MainActivity : AppCompatActivity() {
companion object {
private const val REQUEST_CODE = 1234
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button_open.setOnClickListener {
startActivityForResult(
SecondActivity.createIntent(this),
REQUEST_CODE
)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Log.d("MainActivity", "requestCode: $requestCode, resultCode: $resultCode, data: $data")
}
}
SecondActivity needs to be required before finishsetResult
setResult(Activity.RESULT_OK, intent)
finish()
After
Introduce gradle
implementation "androidx.activity:activity-ktx:$latest_vsersion"
or
implementation "androidx.fragment:fragment-ktx:$latest_vsersion"
class MainActivity : AppCompatActivity() {
private val launcher: ActivityResultLauncher<Intent> =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
activityResult ->
Log.d("MainActivity", activityResult.toString())
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button_open.setOnClickListener {
launcher.launch(SecondActivity.createIntent(this))
}
}
}
Eliminate the annoying resultCode
sum requestCode
, the code is more elegant
Other scenes
See how to use ActivityResultContract in several common scenarios:
Select a document
Open the file manager, select the picture and return uri
, first look at the implementation based on onActivityResult:
class MainActivity : AppCompatActivity() {
companion object {
private const val REQUEST_CODE_CHOOSER = 1234
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button_get_content.setOnClickListener {
startActivityForResult(
Intent(Intent.ACTION_GET_CONTENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "image/*"
},
REQUEST_CODE_CHOOSER
)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_CHOOSER && resultCode == Activity.RESULT_OK) {
Log.d("MainActivity", "uri: ${
data?.data}")
}
}
}
After implementation based on ActivityResultContracts:
class MainActivity : AppCompatActivity() {
private val launcher = registerForActivityResult(ActivityResultContracts.GetContent()) {
uri ->
Log.d("MainActivity", "uri: $uri")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button_get_content.setOnClickListener {
launcher.launch("image/*")
}
}
}
ActivityResultContracts.GetContent
It is one of several contracts preset by the system:
Of course, in addition to the above presets Contracts
, you can also ActivityResultContracts
customize your own Contracts by inheriting
Permission request
The process of requestPermission and startActivityForResult is similar:
//权限请求
ActivityCompat.requestPermissions(this, arrayOf(WRITE_EXTERNAL_STORAGE), REQUEST_CODE)
//返回结果
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "result: granted", Toast.LENGTH_LONG).show()
}
return
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
Implementation based on ActivityResultContract:
// 设置回调
private val launcher = registerForActivityResult(RequestPermission()) {
if (it) {
Toast.makeText(this, "result: granted", Toast.LENGTH_LONG).show()
}
}
// 请求权限
launcher.launch(WRITE_EXTERNAL_STORAGE)
Implementation principle
The principle of ActivityResultContract is relatively simple, interested students can refer to the in-depth understanding of ActivityResultContracts