본문 바로가기

Programming/Android

[Android] Parcelable 에 대한 쉬운 이해

반응형
 안녕하세요 명동 콜링입니다.

오늘은 Android에서 Model Class를 다룰 때 사용하는 Serializable 의 한 분류인 Parcelable에 대해 써보려고 합니다.

일단 Serializable이란 무엇인가, 영어의 뜻을 풀이하자면 '직렬화' 라고 얘기할 수 있는데 막연히 '직렬화' 라고 얘기하기엔 무슨 뜻인지 이해 하기 어렵습니다. 그래서 Android 시스템에서 동작하는 방식으로 이야기 하자면,

A Activity에서 B Activity로 데이터를 전달할 때, 데이터를 묶어서 전달한다

 라고 쉽게 풀이할 수 있습니다. 이해를 하는데 도움이 되도록 많이 함축된 문장이지만 이 안에는 "하나의 Class화 된 여러 데이터들이 순서대로 Byte형식으로 변환되어 A -> B로 전달된다." 는 식의 어려운 말 들이 포함되어 있기 때문에 패스를 하도록 하겠습니다.

 여기까지 Serializable의 정의에 대해 간단히 알아봤고 이제는 본격적으로 이 글의 주제인 Parcelable에 대해 알아보도록 합시다.

 일단 Parcel, '소포', '꾸러미' 라는 뜻을 가지고 있습니다. 이 단어의 뜻처럼 Android에서의 Parcel이라는 것도 "여러 데이터가 하나의 꾸러미(Class) 안에 담겨 있다." 라는 의미를 가지게 됩니다. 그래서 이 데이터 꾸러미가 A Activity에서 B Activity로 한꺼번에 전달되고 받아 볼 수 있도록 해 주는 것이 Parcelable의 의미가 되겠습니다.

 그럼 이 Parcelable을 어떻게 사용하는 지 보도록 하겠습니다.

 1. 클래스 정의


 먼저 Data(Model) Class를 하나 만들어 보도록 합니다.

public class ProfileCls {
String name;
    int age;
    String gender;
}

간단하게 이름, 나이, 성을 입력 할 수 있는 Class를 만들었습니다. 이 상태에서는 A Activity에서 B Activity로 데이터를 이동 시킬 수 없고 Parcelable을 적용한 후에 Intent를 이용하여 보내고 받을 수 있게 됩니다.

 2. Parcelable 적용


 Parcelable은 Interface입니다. 그래서 implements를 통하여 내부 메소드들을 구현해야 합니다. implements를 하게되면 다음과 같은 메소드들이 자동으로 Override됩니다.

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {

}

이 두 메소드 중에서 사용해야 될 것이 writeToParcel입니다. writeToParcel은 객체가 직렬화되어 보내지기 이전에 데이터를 직렬화시켜주는 메소드로, dest에 순차적으로 Class 내부에 있는 데이터들을 저장시켜놓습니다. 
 그래서 내부 메소드는 다음과 같이 합니다.

public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
    dest.writeInt(age);
    dest.writeString(gender);
}

이름, 나이, 성별 순서대로 Parcel에 담겨지게 되며, 각각 Data type에 맞는 메소드로 작성하시면 되겠습니다.
 하지만 여기까지가 끝은 아닙니다. 바로 객체를 받았을 때 직렬화를 풀어주는 로직을 함께 작성해야 합니다.

public ProfileCls(){}
public ProfileCls(Parcel src){
name = src.readString();
    age = src.readInt();
    gender = src.readString();
}

 Parcel을 이용하여 보내게 되면 받는 쪽에서도 Parcel을 통해서 데이터를 받기 때문에, 생성자를 통해 Parcel을 전달하게 됩니다. 그래서 Parcel형이 들어오는 생성자를 만들게 되었고, Default 생성자도 함께 추가 하였습니다.

 여기까지 작성했다면, 이제 마지막으로 CREATOR라는 것을 만들어야 합니다. 이 Creator가 없다면 데이터를 넘기게 되더라고 Creator가 없다는 Exception을 뿌려주기 때문에 필히 작성을 해줘야 하는 부분입니다. 그래서,

public static final Creator<ProfileCls> CREATOR = new Creator<ProfileCls>() {
@Override  
    public ProfileCls createFromParcel(Parcel in) {
return new ProfileCls(in);  
    }

@Override
    public ProfileCls[] newArray(int size) {
return new ProfileCls[size];
    }
};

이렇게 작성을 해주어야 합니다. Android Studio를 쓴다면 친절하게 자동으로 입력을 해주기 때문에 붉은색의 Lint표시가 없어지지 않았다면 확인해야 할 것 입니다.

import android.os.Parcel;
import android.os.Parcelable;

public class ProfileCls implements Parcelable{
String name;
    int age;
    String gender;

public ProfileCls(){}
public ProfileCls(Parcel src){
name = src.readString();
        age = src.readInt();
        gender = src.readString();
    }

@Override
    public int describeContents() {
return 0;
    }

@Override
    public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
        dest.writeInt(age);
        dest.writeString(gender);
    }

public static final Creator<ProfileCls> CREATOR = new Creator<ProfileCls>() {
@Override
        public ProfileCls createFromParcel(Parcel in) {
return new ProfileCls(in);
        }

@Override
        public ProfileCls[] newArray(int size) {
return new ProfileCls[size];
        }
};
}

이와 같이 Parcelable을 적용한 클래스가 완성이 되었습니다.

 3. 사용

 이제 Parcelable로 된 Class를 A Activity에서 B Activity로 보내는 방법을 간단하게 알아보도록 하겠습니다.

 먼저 A Activity에서 Class 객체의 데이터를 구성합니다.

ProfileCls profile = new ProfileCls();
profile.name = "명동콜링";
profile.age = 29;
profile.gender = "남성";

 다음으로, Intent의 putExtra를 통해서 Parcelable class를 보내게 됩니다.

Intent intent = new Intent(this, SubActivity.class);
intent.putExtra("parcel", profile);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
 여기까지가 A Activity에서 하는 일입니다. 그럼 이제 받는 쪽인 B Activity를 보도록 합시다.

@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Intent data = getIntent();
ProfileCls profile = data.getParcelableExtra("parcel");
System.out.println("이름: "+profile.name);
    System.out.println("나이: "+profile.age);
    System.out.println("성별: "+profile.gender);
}

putExtra를 통해서 보낼 데이터를 넣었다면, 받을 때도 간단하게 getExtra형태인 getParcelableExtra를 통해 데이터를 불러오게 됩니다.

그래서 로그캣에도,


위와 같이 보내진 것을 확인할 수 있는 로그가 찍혀있게 됩니다.

이렇게 쉽게 직렬화를 하여 편하게 데이터를 주고받을 수 있으며, 액티비티가 아니라도 어디서든지 가능합니다.