Насколько безопасна регистрация контрактов с ActivityResultRegistry после onResume в Android?
Следующий код дает мне ошибку, так как регистрация происходит после onResume:
class TempActivity: AppCompatActivity(){
private lateinit var binding: ActivityTempBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityTempBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.tempBtn.setOnClickListener {
val a = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
//SomeCode
}
a.launch(
//SomeIntent
)
}
}
Однако, если я использую activityResultRegistry, я не получаю никаких ошибок. Код
class TempActivity: AppCompatActivity(){
private lateinit var binding: ActivityTempBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityTempBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.tempBtn.setOnClickListener {
val a = activityResultRegistry.register("key", ActivityResultContracts.StartActivityForResult()){
// SomeCode
}
a.launch(
//Some Intent
)
}
}
Последний код запускается без проблем и запускает соответствующий интент. Я просто хочу знать, насколько безопасен последний и есть ли нежелательное поведение, о котором я должен знать?
1 ответ
Это дает вам ошибку, потому что вы регистрируете контракт условно после того, как действие находится в своем жизненном цикле.
Гид говорит :
Вы всегда должны вызывать в одном и том же порядке для каждого создания вашего фрагмента или действия, чтобы гарантировать, что результаты обработки доставляются правильному обратному вызову.
Понятно, что если вы регистрируете что-то после создания действия, и это происходит только при выполнении условия (события щелчка в данном случае), порядок регистрации не может быть обеспечен.
Лучшим решением было бы зарегистрировать контракт до создания действия и просто вызвать
безопасно вызывать перед созданием фрагмента или действия, что позволяет использовать его непосредственно при объявлении переменных-членов для возвращаемых экземпляров ActivityResultLauncher.
Итак, в вашем случае Activity будет выглядеть так:
class TempActivity: AppCompatActivity() {
private lateinit var binding: ActivityTempBinding
// registering the contract here
private val a = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
//SomeCode
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityTempBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.tempBtn.setOnClickListener {
// launching the registered contract
a.launch(
//SomeIntent
)
}
}
}
Дальнейшее объяснение:
Это удобный метод, который внутренне вызывает реестр
В вашем конкретном случае, если действие воссоздается, пока вы ожидаете возврата запущенного контракта (например, происходит изменение конфигурации или система просто убивает приложение), обратный вызов будет удален из реестра (ключ остается там, хотя ), что означает, что он не будет вызываться с результатами.
Итак, подведем итог: вы можете ( должны ) безопасно зарегистрировать любой контракт в качестве поля участника в своей деятельности или в