Не уверен, смогу ли я ответить на все ваши вопросы, но вот мои два цента:
Ваш код выглядел следующим образом при сбое приложения:
btn_scan.setOnClickListener {
val mIntent = Intent(applicationContext, Scanner::class.java)
mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
mIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
applicationContext.startActivity(mIntent)
}
В сообщении об ошибке сказано, что вы должны использовать FLAG_ACTIVITY_NEW_TASK
при запуске Activity
вне контекста Activity
. Вы использовали контекст Application
, который похож на двоюродного брата контекста Activity
в отношении наследования (см. ContextWrapper для подклассов и их отношений), поэтому флаги Intent
были проверены и необходимые Флаг отсутствовал.
Но почему флаг может отсутствовать, если вы устанавливаете его явно?
mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
Это потому, что вы сразу назначаете другое значение для mIntent.flags :
mIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
Если вы хотите иметь оба флага, вы должны добавить их:
mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + Intent.FLAG_ACTIVITY_CLEAR_TOP
Теперь приложение больше не падает.
Но это контекст Application
здесь даже необходим? В конце концов, ваш код является частью Activity
, а Activity
является косвенным подклассом Context
.
Возможно, вы пробовали следующее, и это сработало:
btn_scan.setOnClickListener {// Note: your IDE tells you "it: View!"
val mIntent = Intent(applicationContext, Scanner::class.java)
mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
mIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
this.startActivity(mIntent)
}
Потому что внутри OnClickListener
лямбда, View
обозначается как «оно», нет никакой двусмысленности: «это» относится к Activity
, без cra * sh. (Конечно, теперь вы можете пропустить Intent.FLAG_ACTIVITY_NEW_TASK
)
Вещи выглядят иначе, если у вас есть что-то вроде этого:
with(btn_scan){ // this: Button!
setOnClickListener{ // it: View!
val mIntent = Intent(applicationContext, Scanner::class.java)
mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + Intent.FLAG_ACTIVITY_CLEAR_TOP
this.startActivity(mIntent)
}
}
Теперь ваша IDE не будет принимать this.startActivity(mIntent)
. Это потому, что здесь «это» относится к Button
. Если вы хотите другое, «внешнее это», вы должны явно сказать, какой именно. В Kotlin вы делаете это, добавляя @ActivityName.
Полагаю, то же самое касается кода сопрограммы внутри Activity
(хотя я должен признаться, что я еще не эксперт по сопрограммам): всякий раз, когда Activity
"this" скрывается за каким-то локальным "this" , вам нужна аннотация.
Возвращаемся к знакомой почве: свойство context
для Fragment
является контекстом Activity
, если Fragment
присоединено к Activity
, иначе это null
. Так что, если это не null
, вы можете использовать его для запуска Activity
.
Но вы даже можете использовать свойство Button
context
, поскольку оно также идентично контексту Activity
:
with(btn_scan){ // this: Button!
setOnClickListener{
val mIntent = Intent(applicationContext, Scanner::class.java)
mIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
this.context.startActivity(mIntent)
}
}