Как правильно вызвать контекст для запуска действия - PullRequest
2 голосов
/ 27 января 2020

Поскольку у меня возникли сбои этого жанра:

Для вызова startActivity () вне контекста Activity требуется флаг FLAG_ACTIVITY_NEW_TASK. Это действительно то, что вы хотите?

Я начал задумываться о правильном использовании контекста для startActivity-Intent.

Это был мой Kotlin -Code (Activity -> Activity):

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)    

        }

, который я смог исправить с помощью «this»:

btn_scan.setOnClickListener {
            val mIntent = Intent(this, Scanner::class.java)
            mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            mIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
            this.startActivity(mIntent)    

        }

Но теперь я немного не уверен в правильном использовании этого, так как доступ например, из внутренней функции нужно this@ActivityName. Так что я хотел бы попросить вас вежливо объяснить мне, как узнать, какой контекст является правильным, при запуске действия из действия, из фрагмента или из функции или использования CoroutineScope

Спасибо

Ответы [ 2 ]

2 голосов
/ 27 января 2020

Не уверен, смогу ли я ответить на все ваши вопросы, но вот мои два цента:

Ваш код выглядел следующим образом при сбое приложения:

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)
        }
    }
0 голосов
/ 28 января 2020

если использовать kotlin

    btn_scan.setOnClickListener {
            val mIntent = Intent(this, Scanner::class.java)
            mIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
            this.startActivity(mIntent)    
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...