일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 2022 플러터 안드로이드 스튜디오
- 스택 자바 코드
- 안드로이드 유닛테스트란
- android retrofit login
- 큐 자바 코드
- 안드로이드 유닛 테스트
- 서비스 vs 쓰레드
- 안드로이드 레트로핏 crud
- rxjava cold observable
- 안드로이드 라이선스
- 멤버변수
- rxjava disposable
- 안드로이드 레트로핏 사용법
- 자바 다형성
- 안드로이드 os 구조
- Rxjava Observable
- ar vr 차이
- 스택 큐 차이
- rxjava hot observable
- 클래스
- android ar 개발
- jvm이란
- 서비스 쓰레드 차이
- 객체
- 안드로이드 라이선스 종류
- 안드로이드 유닛 테스트 예시
- 플러터 설치 2022
- ANR이란
- jvm 작동 원리
- 2022 플러터 설치
- Today
- Total
나만을 위한 블로그
[Kotlin] 안드로이드 인텐트로 액티비티 간 데이터 전달하는 법 본문
안드로이드 스튜디오에서 코틀린으로 앱을 만들 때 자바를 쓸 때처럼 인텐트로 액티비티를 전환하거나, 인텐트에 데이터를 넣어 다른 액티비티에서 사용해야 할 필요가 있다.
이 글에선 이런 처리들을 어떻게 하는지 포스팅하려고 한다.
먼저 MainActivity의 XML 코드다. 아이디와 비밀번호만 사용할 거기 때문에 간단하게 짰다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="메인 액티비티"
android:textSize="30sp"
android:gravity="center"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="70dp"
android:orientation="horizontal"
android:weightSum="1">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".3"
android:gravity="end"
android:text="아이디"
android:layout_marginRight="30dp"/>
<EditText
android:id="@+id/edit_id"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".7"
android:hint="아이디 입력"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:orientation="horizontal"
android:weightSum="1">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".3"
android:gravity="end"
android:text="비밀번호"
android:layout_marginRight="30dp"/>
<EditText
android:id="@+id/edit_pw"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".7"
android:hint="비밀번호 입력"/>
</LinearLayout>
<Button
android:id="@+id/login_btn"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="50dp"
android:text="로 그 인"/>
<Button
android:id="@+id/register_btn"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="50dp"
android:text="회 원 가 입"/>
</LinearLayout>
다음은 .kt 파일을 코딩한다.
class MainActivity : AppCompatActivity()
{
private val TAG: String = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
login_btn1.setOnClickListener {
val id = edit_id.text.toString()
val pw = edit_pw.text.toString()
if (id == "123" && pw == "123")
{
Log.e(TAG, "로그인 성공")
}
val intent = Intent(this, AfterLoginActivity::class.java)
intent.putExtra("id", id)
intent.putExtra("pw", pw)
startActivity(intent)
}
}
}
아이디, 비밀번호에 모두 123이란 값을 넣고 버튼을 누르면 로그인 성공이라는 로그가 나오고 다른 액티비티로 이동되도록 했다.
그럼 이동된 액티비티에서 로그를 찍어서 정상적으로 데이터가 이동됐는지 확인하자.
class AfterLoginActivity : AppCompatActivity()
{
private val TAG: String = "AfterLoginActivity"
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_after_login)
if (intent.hasExtra("id") && intent.hasExtra("pw"))
{
val id = intent.getStringExtra("id")
val pw = intent.getStringExtra("pw")
Log.e(TAG, "메인에서 받아온 id : $id, pw : $pw")
}
else
{
Log.e(TAG, "가져온 데이터 없음")
}
}
}
if()에 hasExtra()를 넣어서 키값이 있는지 체크하는 부분이 있는 걸 빼면 별로 특별한 코드는 없다.
이제 앱을 빌드해보면 아래와 같은 로그가 찍힌다.
깔끔하게 로그에 찍혀나오는 걸 볼 수 있다.
여기서 생각해봐야 할 것이 지금은 아이디와 비밀번호라는 2가지 값만 이동하지만, 만약 10개가 넘는 데이터를 옮겨야 한다면 어떨까?
그 때마다 일일이 putExtra()로 값 넣고 목표지에서 getStringExtra()같은 get()으로 인텐트를 풀고 처리하는 방법도 있다.
그리고 새로 클래스를 하나 파서 그 클래스의 변수를 넘기게 하는 방식도 있을 것이다.
아래에서 설명하는 방식이 바로 클래스의 변수를 인텐트에 넣어 이동시키는 방식이다.
예시기 때문에 위에서 사용한 아이디, 비밀번호 2개 변수만 갖는 Person이라는 클래스를 만들겠다.
import android.os.Parcel
import android.os.Parcelable
class Person constructor(val id: String, val pw: String) : Parcelable
{
constructor(parcel: Parcel) : this(
parcel.readString()?: "",
parcel.readString()?: ""
)
{
//
}
override fun writeToParcel(dest: Parcel, flags: Int)
{
dest.writeString(id)
dest.writeString(pw)
}
override fun describeContents(): Int
{
return 0
}
companion object CREATOR : Parcelable.Creator<Person>
{
override fun createFromParcel(parcel: Parcel): Person
{
return Person(parcel)
}
override fun newArray(size: Int): Array<Person?>
{
return arrayOfNulls(size)
}
}
}
constructor() 뒤의 : 표시는 자바의 implements 키워드다. : Parcelable은 implements Parcelable과 같은 효과를 낸다.
그런데 Parcelable은 뭐하는 키워드일까?
Parcelable은 안드로이드에서 액티비티, 프래그먼트 간에 데이터를 주고받을 때 구현하는 기법이다.
직렬화/역직렬화라는 이름으로 불리기도 한다. Parcelable 말고도 Serializable이라는 기법도 있지만 이 글에선 생략한다.
Parcelable은 안드로이드 SDK의 라이브러리로, Serializable보다 속도가 빠르고 안드로이드에서 사용하기를 권장하는 기법이다.
단점이라면 개발자가 만들어줘야 하는 요소들이 좀 있어서 키보드를 두드려야 하는 것 정도다.
실제로 저 코드를 처음부터 만든다면 이런 꼴이 된다. 먼저 Person이란 클래스를 만들고, 생성자로 id와 pw를 만든 뒤, 뒤에 : Parcelable 키워드를 붙였다.
class Person constructor(val id: String, val pw: String) : Parcelable
{
}
이 상태에서 class Person을 보면 이 부분에 빨간 줄이 그어져 있다.
이 부분에 커서를 찍고 Alt + Enter를 누르면 아래와 같은 화면이 나온다.
여기서 1번 'Add Parcelable Implementation'을 선택하면 갑자기 3개의 메서드들이 자동으로 구현된다.
class Person constructor(val id: String, val pw: String) : Parcelable
{
constructor(parcel: Parcel) : this(
parcel.readString(), parcel.readString()
)
{
//
}
override fun writeToParcel(parcel: Parcel, flags: Int)
{
parcel.writeString(id)
parcel.writeString(pw)
}
override fun describeContents(): Int
{
return 0
}
companion object CREATOR : Parcelable.Creator<Person>
{
override fun createFromParcel(parcel: Parcel): Person
{
return Person(parcel)
}
override fun newArray(size: Int): Array<Person?>
{
return arrayOfNulls(size)
}
}
}
그런데 constructor(parcel: Parcel) : this() 안의 readString() 두 곳에서 빨간 줄이 그어져 있다.
이 부분은 위에서 먼저 보여준 코드로 바꾸거나, Alt + Enter를 눌러 toString()을 붙여주면 사라진다.
toString()을 붙인다면 아래와 같은 코드가 된다.
class Person constructor(val id: String, val pw: String) : Parcelable
{
constructor(parcel: Parcel) : this(
parcel.readString().toString(), parcel.readString().toString()
)
{
//
}
override fun writeToParcel(parcel: Parcel, flags: Int)
{
parcel.writeString(id)
parcel.writeString(pw)
}
override fun describeContents(): Int
{
return 0
}
companion object CREATOR : Parcelable.Creator<Person>
{
override fun createFromParcel(parcel: Parcel): Person
{
return Person(parcel)
}
override fun newArray(size: Int): Array<Person?>
{
return arrayOfNulls(size)
}
}
}
어떤 형태를 써도 상관없는 듯하니 자신에게 편한 방법을 사용하자.
그럼 이제 Person 클래스를 써서 생성자에 아이디, 비밀번호를 정의한 뒤 다른 액티비티로 이동시켜보자.
MainActivity와 AfterLoginActivity에 코드를 몇 줄 추가한다.
class MainActivity : AppCompatActivity()
{
private val TAG: String = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
login_btn1.setOnClickListener {
val id = edit_id.text.toString()
val pw = edit_pw.text.toString()
if (id == "123" && pw == "123")
{
Log.e(TAG, "로그인 성공")
}
val intent = Intent(this, AfterLoginActivity::class.java)
intent.putExtra("id", id)
intent.putExtra("pw", pw)
val person = Person("123", "123") // <- 추가된 부분
intent.putExtra("person", person)
startActivity(intent)
}
}
}
class AfterLoginActivity : AppCompatActivity()
{
private val TAG: String = "AfterLoginActivity"
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_after_login)
if (intent.hasExtra("id") && intent.hasExtra("pw"))
{
val id = intent.getStringExtra("id")
val pw = intent.getStringExtra("pw")
val person = intent.getParcelableExtra<Person>("person")
if (person != null) // Null 체크
{
Log.e(TAG, "메인에서 받아온 id : $id, pw : $pw, person : ${person.id} / ${person.pw}")
}
}
else
{
Log.e(TAG, "가져온 데이터 없음")
}
}
}
주의할 것은 AfterLoginActivity에 있는 if (person != null)문의 중괄호 안이다.
코틀린은 문자열 안이라도 $만 붙인다면 변수를 가져와 쓸 수 있다. 그런데 Parcelable을 구현한 클래스의 변수값을 표시하는 곳은 앞뒤로 {}가 붙어있는 걸 볼 수 있다.
이 괄호들을 없애고 그냥 $person.id와 $person.pw라고 쓰면 무슨 일이 일어날까? 결과는 직접 확인해보고 왜 그런지도 알아보자.
위처럼 만들고 앱을 빌드하면 아래와 같은 로그가 출력된다.
생성자로 넣어준 2개의 123이 로그에 찍혀나오는 걸 볼 수 있다.
'개인 공부 > Kotlin' 카테고리의 다른 글
[Kotlin] is 연산자와 as 연산자의 차이 (0) | 2021.05.23 |
---|---|
[Kotlin] 확장 함수(Extension Functions)란? (0) | 2020.11.01 |
[Kotlin] 안드로이드에서 코틀린으로 쉐어드 프리퍼런스 사용하는 법 (0) | 2020.10.25 |
[Kotlin] 코틀린의 컬렉션(List, Map, Set) (0) | 2020.10.17 |
[Kotlin] 코틀린에서의 변수 선언법(val과 var의 차이, null) (0) | 2020.10.17 |