Intent
인텐트는 메시징 객체이다. 즉, 어떠한 구성요소들 사이에서 통신을 촉진해주는 매개체라고 보면된다.
컴포넌트가 운영체제와 통신하는 데 사용할 수 있는 객체이다.
컴포넌트는 액티비티(activity), 서비스(service), 브로드캐스트 수신자(broadcast receiver), 콘텐트 제공자(content provider)도 있다.
인텐트는 하고자 하는 것을 안드로이드 운영체제에 알려주는 객체이다.
인텐트의 생성자 이다.
Intent(packageContext : Context, class: Class<?>)
인텐트가 진행되는 방식 (예)
Activity | ----------------------->>>>>> | ActivityManager |
-------1, 인텐트 객체 생성--------------------> | 2. startActivity(Intent) | 3. instance 생성 |
4. 원하는 것을 실행한다. | <<<<<-------------------------- |
크게 세가지 방식으로 사용됨.
1. 액티비티 시작
2. 서비스의 시작
3. 브로드 캐스트 전달
1. 액티비티 시작
액티비티Activity는 앱 안의 단일 화면을 나타낸다.
액티비티의 새 인스턴스Instance를 시작하려면 인텐트를 startActivity()로 전달하면된다.
JAVA
Intent name = new Intent(startActivity.this , goActivity.class);
startActivity(name);
KOTLIN
val intent = Intent(this, ExampleActivity::class.java)
startActivity(intent)
이런식으로 인텐트를 선언해준뒤, 액티비티의 시작점과 이동 클래스를 설정해주면된다.
그리고나서 startActivity에 해당 인텐트를 넣어주어 시작하면된다.
이러한 과정은 어떠한 이벤트를 실행할 때, 예를들어 onclick 같은것에 넣어주면 실행된다.
액티비티가 완료되었을때 결과를 수신하려면, startActivityForResult() 를 호출합니다.
액티비티는 해당 결과를 이 액티비티의 onActivityResult() 콜백에서 별도의 인텐트 객체로 수신합니다.
인텐트의 종류는 두가지이다.
명시적 인텐트 / 암시적 인텐트
Explicit Intent - 명시적 인텐트
Context객체와 Class객체를 사용해서 생성하는 Intent를 말한다.
명시적 인텐트는 앱 내부에 있는 액티비티를 시작시키기 위해 사용한다.
Implicit Intent - 암시적 인텐트
한 애플리케이션의 액티비티에서 다른 애플리케이션의 액티비티를 시작시키려면 암시적 인텐트를 생성한다.
암시적 인텐트를 사용할 때는 원하는 작업을 안드로이드 운영체제에 알려준다.
그러면 해당 작업을 할 수 있다고 자신을 알린 액티비티를 안드로이드 운영체제가 찾아서 시작시킨다.
단, 안드로이드 OS가 그런 능력을 가진 액티비티를 두 개 이상 찾으면 사용자가 선택할 수 있게 해준다.
명시적 인텐트의 데이터 전달
Intent의 엑스트라(extra)값으로 전달된다.
Extra - 엑스트라
엑스트라는 호출하는 액티비티가 인텐트에 포함시킬 수 있는 임의 데이터로, 생성자 인자로 생각할 수 있다.
App(sample) | Android OS | ||
MainActivity(example) | ActivityManager | ||
startActivity(Intent) | Intent component = secondActivity extra = EXTRA_ANSWER_IS_TRUE |
| | 🔽 |
|
(Intent) | |||
SecondActivity | <<---- |
엑스트라는 키와 값이 한 쌍으로 된 구조이다. (Bundle 객체의 구조와 동일하다. )
값을 저장하기 위해서는 putExtra()함수를 사용하여 값과 키를 넣어준다.
Intent.putExtra(...)
Intent.putExtra(name: String , value: Boolean) 의 형태로 사용한다.
단순히 인텐트로 정보를 보내는 것 말고 다시 돌려받기 위해서
startActivityForResult(Intent, Int)
결과 데이터 설정하기, 부모 액티비티에 데이터를 돌려주기 위해 자식 액티비티에서 호출하는 함수이다.
두 가지의 함수가 있다.
setResult ( resultCode: Int)
setResult ( resultCode: Int, data: Intent)
일반적으로 결과코드(resultCode) 는 사전 정의된 두개의 상수로 되어있다.
Activity.RESULT_OK
Activity.RESULT_CANCELED
로 되어있는데, OK 는 -1을 상징하며, CANCELED 는 1을 상징한다.
자식 액티비티가 어떻게 끝났는지에 따라 부모 액티비티에서 다른 액션을 취할 때 결과 코드를 사용하면 유용하다.
setResult() 함수는 꼭 호출해야하는 것은 아니다. 즉, startActivityForResult()로 시작됬다면, 결과 코드가 항상 부모 액티비티에게 변환된다. 이 경우 사용자가 백 버튼을 누르면 부모 액티비티는 결과 코드로 Activity.RESULT_CANCELED를 받게 된다는 점을 기억하자.
자식 액티비티에서 다시 intent에 정보를 넣는 형식으로 데이터를 넣어주고, setResult() 함수를 통해서 다시 보내주는 개념이다.
private const val EXTRA_ANSWER_IS_TRUE = "com.....answer_is_true"
const val EXTRA_ANSWER_IS_SHOWN = "com....answer_shown"
class ChildActivity : AppCompatActivity() {
private lateinit var answerTextView : TextView
private lateinit var showAnswerButton : Button
private var answerIsTrue = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_cheat)
...
showAnswerButton.setOnClickListener {
val answerText = when{
answerIsTrue -> R.string.true_button
else -> R.string.false_button
}
answerTextView.setText(answerText)
setAnswerShowResult(true)
}
}
private fun setAnswerShowResult(isAnswerShown: Boolean) {
val data = Intent().apply {
putExtra(EXTRA_ANSWER_IS_SHOWN, isAnswerShown)
}
setResult(Activity.RESULT_OK, data)
}
...
}
setAnswerShowResult() 함수를 따로 생성하여 캡슐화 해주고, 여기에 부모 액티비티에서 인텐트를 만든 것처럼 인텐트를 선언하여 정보를 넣어주고, setResult() 함수를 통해 값을 넣어주면된다. 그리고 이 setAnswerShowResult() 함수는 private으로 해주고, onCreate에 해당되는 기능에 값을 넣어서 실행해주면 된다. 이렇게 되면 자동으로 OK인지 CANCELD인지 값을 넣어서 보내고 그 데이터도 같이 이동하게 된다.
부모액티비티에서 자식으로부터 반응을 받은 데이터 열기 위해서는
onActivityResult ( requestCode : Int, resultCode: Int, data: Intent )
위의 함수를 이용하여 부모액티비티에서 자식이 보낸 데이터 값을 확인 한다.
자식액티비티에서 부모로 다시 보내진 데이터를 뷰모델로 상태 보존하기.viewmodel - view - model 로 프로젝트가 구성되어있다면, 이렇게 인텐트로 정보가 왔다갔다 한 경우 난감하다. 이러한 경우 viewmodel에도 자식에서 보내온 대답 데이터를 새로운 속성으로 뷰모델에 저장해주면 된다.
간단하게 그 정보를 담아줄 객체를 뷰모델에 선언해준다. 그리고 부모 액티비티에서 해당 데이터를 뷰모델 데이터해당 객체로 반영해주면 된다. onActivityResult() 함수에서 이러한 작업을 처리해주면 된다.
{
...
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(resultCode != Activity.RESULT_OK){
return
}
if(requestCode== REQUEST_CODE_CHEAT ){
quizViewModel.isCheater = data?.getBooleanExtra(EXTRA_ANSWER_IS_SHOWN, false)?: false
}
}
...
}
quizViewModel에 선언된 isCheater라는 객체에 자식액티비티에서 보내온 Data 인텐트를 Get 함수를 통해 정보를 꺼내 반영한다.
암시적 인텐트의 구성 요소
1. 수행하고자 하는 액션 Action
Intent 클래스의 상수이다.
예시) web URL을 보기 원한다면, Intent.ACTION_VIEW 를 액션으로 사용하며, 텍스트 등을 전송할 때는 Intent.ACTION_SEND를 사용한다.
이외에도 여러 상수가 있다.
2. 데이터의 위치
web페이지의 URL 과 같은 장치 외부의 것이 될 수 있다. 또는 파일에 대한 URI 나 Content Provider 의 레코드를 가리키는
콘텐츠 URI 도 될 수 있다.
3. 액션에서 필요한 데이터의 타입
text/html or audio/mpeg3 과 같은 MIME 타입이다. 인텐트가 데이터의 위치를 포함하면 해당 데이터로부터 타입을 유추할 수 있다.
4. 선택적으로 사용하는 카테고리
액션이 무엇을 하는지를 나타내는 데 사용되는 것이라면 카테고리는 액티비티를 어디서, 언제, 어떻게 사용할지를 나타낸다.
액티비티가 최상위 수준의 앱 론처에 보여야 함을 나타내기 위해 안드로이드는 android.intent.category.LAUNCHER 카테고리를 사용한다.
반면에 액티비티의 패키지에 관한 정보를 사용자에게 보여주되 론처에는 나타내지 않아야 하는 액티비티를 나타내려면 android.intent.category.INFO카테고리를 사용한다.
'Programming > Android' 카테고리의 다른 글
[Android] Dagger2 (0) | 2020.12.16 |
---|---|
🥋 2. JetPack & Flutter Widget (0) | 2020.10.27 |
Shortcut 단축키 모음 (0) | 2020.06.12 |