Рекомендований підхід ActivityResultRegistry
ComponentActivity
тепер надає функцію, ActivityResultRegistry
яка дозволяє обробляти потоки startActivityForResult()
+ onActivityResult()
, а також requestPermissions()
+, onRequestPermissionsResult()
не переважаючи методи у вашому Activity
або Fragment
, підвищує безпеку типу черезActivityResultContract
та забезпечує гачки для тестування цих потоків.
Настійно рекомендується використовувати API Result API, введені в AndroidX Activity 1.2.0-alpha02 та Fragment 1.3.0-alpha02.
Додайте це до свого build.gradle
def activity_version = "1.2.0-alpha03"
// Java language implementation
implementation "androidx.activity:activity:$activity_version"
// Kotlin
implementation "androidx.activity:activity-ktx:$activity_version"
Як користуватися попередньо складеним договором?
Цей новий API має такі попередньо вбудовані функції
- Візьміть відео
- PickContact
- GetContent
- GetContents
- OpenDocument
- OpenDocuments
- OpenDocumentTree
- CreateDocument
- Циферблат
- Сфотографувати
- Запит дозволу
- RequestPermissions
Приклад, який використовує договір takePicture:
private val takePicture = prepareCall(ActivityResultContracts.TakePicture())
{ bitmap: Bitmap? ->
// Do something with the Bitmap, if present
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener { takePicture() }
}
То що тут відбувається? Давайте трохи розбимо його. takePicture
- це лише зворотний виклик, який повертає нульову растрову карту - незалежно від того, чи ні, чи ні onActivityResult
процес був успішним. prepareCall
потім реєструє цей виклик у новій функції під ComponentActivity
назвою ActivityResultRegistry
- ми повернемося до цього пізніше. ActivityResultContracts.TakePicture()
є одним із вбудованих помічників, які Google створила для нас, і, нарешті, виклик takePicture
фактично запускає Намір так само, як ви ранішеActivity.startActivityForResult(intent, REQUEST_CODE)
.
Як написати індивідуальний контракт?
Простий контракт, який приймає Int як Вхідний і повертає Рядок, який вимагає Діяльність, повертається в результаті Намір результату.
class MyContract : ActivityResultContract<Int, String>() {
companion object {
const val ACTION = "com.myapp.action.MY_ACTION"
const val INPUT_INT = "input_int"
const val OUTPUT_STRING = "output_string"
}
override fun createIntent(input: Int): Intent {
return Intent(ACTION)
.apply { putExtra(INPUT_INT, input) }
}
override fun parseResult(resultCode: Int, intent: Intent?): String? {
return when (resultCode) {
Activity.RESULT_OK -> intent?.getStringExtra(OUTPUT_STRING)
else -> null
}
}
}
class MyActivity : AppCompatActivity() {
private val myActionCall = prepareCall(MyContract()) { result ->
Log.i("MyActivity", "Obtained result: $result")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
button.setOnClickListener {
myActionCall(500)
}
}
}
Перегляньте цю офіційну документацію для отримання додаткової інформації.