ActivityResultRegistry - рекомендуемый подход
ComponentActivity
теперь предоставляет, ActivityResultRegistry
который позволяет вам обрабатывать потоки startActivityForResult()
+, onActivityResult()
а также requestPermissions()
+ onRequestPermissionsResult()
без переопределения методов в вашем Activity
или Fragment
, обеспечивает повышенную безопасность типов через ActivityResultContract
и предоставляет ловушки для тестирования этих потоков.
Настоятельно рекомендуется использовать API Result Activity, представленные в 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 имеет следующие встроенные функции
- TakeVideo
- 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 в качестве входных данных и возвращает строку, запрошенную Activity, возвращается в результате Intent.
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)
}
}
}
Проверьте эту официальную документацию для получения дополнительной информации.