Android

액티비티 (7) : Parcelable과 Bundle

까망사과 2022. 5. 13. 02:00

액티비티 간 데이터 전송

startActivity()로 새 액티비티를 시작할 때 전달할 Intent 객체를 생성할 때 putExtra()를 사용하여 파라미터를 전달할 수 있다. 다음과 같이 사용할 수 있다.

val intent = Intent(this, NewActivity::class.java).apply {
    putExtra("media_id", "a1b2c3")
}
startActivity(intent)


OS는 인텐트 안의 Bundle을 포장하고 나서 새 액티비티를 생성하고 데이터를 다시 푼 다음 새 액티비티에 인텐트를 전달한다. Intent 객체에 원시 타입 데이터를 저장할 때에는 Bundle을 사용하는 것을 권장한다. Bundle 클래스는 Parcel을 사용하는 마셜링/언마셜링 작업에 매우 최적화되어있다.

액티비티에 합성 및 복합 객체를 전달해야 하는 경우도 있을 수 있다. 이럴 때는 Parcelable 인터페이스를 구현하고 적절한 writeToParcel()을 제공해야 한다. 또한 Parcelable.Creator 인터페이스를 구현하는 CREATOR라는 필드도 제공해야 한다. CREATORcreateFromParcel()Parcel을 현재 객체로 변환하는 데 사용한다.

인텐트로 데이터를 전달할 때 데이터 용량을 수 KB 정도로 제한해야 한다.
너무 많은 데이터를 전달하면 TransactionTooLargeException이 발생할 수 있다.

프로세스 간 데이터 전송

위에서 설명한 액티비티 간 데이터 전송과 유사하지만 커스텀 Parcelable을 사용하지 않는 것이 좋다. 커스텀 Parcelable 객체를 다른 앱으로 전송한다면 전송하는 앱과 전송받는 앱이 사용하는 클래스가 정확히 동일한 버전이어야 한다. 일반적으로 커스텀 클래스는 양 앱이 공동으로 사용하는 라이브러리일 수 있다. 앱이 커스텀 Parcelable을 시스템에 전송하려 하면 에러가 발생할 수 있다. 시스템이 인식하지 못하는 클래스를 언마셜링할 수 없기 때문이다.

예를 들어 앱이 AlarmManager를 사용하여 알람을 설정하고 알람 인텐트에 커스텀 Parcelable을 사용한다 하자. 알람이 울리면 시스템이 인텐트의 엑스트라 Bundle에 알람 반복 횟수를 추가한다. 이로 인해 시스템이 엑스트라 Bundle에서 커스텀 Parcelable을 제거할 수 있다. 이 제거로 인해 앱이 수정된 알람 인텐트를 수신할 때 앱이 크래시될 수 있다. 앱이 더 이상 존재하지 않는 엑스트라를 수신하려 하기 때문이다.

바인더 트랜잭션 버퍼는 현재 크기가 1MB로 고정되어 있으며 이는 프로세스를 대상으로 진행 중인 모든 트랜잭션이 공유한다. 이 제한은 액티비티 수준이 아니라 프로세스 수준에 적용되기 때문에 이러한 트랜잭션은 onSaveInstanceState(), startActivity() 등 앱의 모든 바인더 트랜잭션을 포함한다. 용량 제한을 초과하면 TransactionTooLargeException이 발생한다.

특히 savedInstanceState의 경우 데이터의 양은 적게 유지되어야 한다. 사용자가 액티비티로 돌아올 수 있는 한(액티비티의 프로세스가 종료되었더라도) 시스템 프로세스가 이를 유지해야 하기 때문이다. 저장된 상태는 50K 이하로 유지하는 것을 권장한다.

안드로이드 7.0(API 레벨 24) 이상 버전에서 TransactionTooLargeException은 런타임 예외로 발생한다.
그 미만 버전에서는 로그캣에 경고 메시지만 표시된다.