프로그래밍/Android

안드로이드 Custom Object Intent로 넘기기, Parcelable 구현

Lou Park 2016. 6. 27. 18:01

내가 만든 클래스 넘기기

(마인크래프트 앱 개발기 3편) 7월 업데이트를 위해 리팩토링을 하면서,

데이터 타입에 대한 정리는 끝났으니 이제 전송에 관련된 일을 처리해야했다.


나는 ItemDB라고 하는 클래스를 만들어  아이템 정보를 관리하고 있다.

그러나 특성상 ItemDB 자체를 인텐트로 넘겨야 더 좋은 성능을 낼 수 있는 상황이 왔다.

intent.putExtra(key, value)로 보내어 value 값이 맞는 아이템을 500개 리스트에서 일일이 찾기 보다는

그냥 ItemDB 하나만 심플하게 보내는 방법이 좋아보였다.

그러나 putExtra()는 한정된 자료형만 전송할 수 있는 단점이 있기에, 어떻게 해결하면 좋을지 찾아보다가

Parcelable 또는 Serializable 을 이용해 커스텀 오브젝트를 전송할 수 있다는 사실을 알게 되었다.


ItemDB.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ItemDB {    
    private final String TYPE_STRING = "string";
    private final String TYPE_DRAWABLE = "drawable";
    private int name;
    private int desc;
    private float hunger;
    private float armor;
    private float cooldown;
    private String attack;
    private String pc_ver;
    private String pe_ver;
    private String grid;
    private int icon;
    private Category category;
}
cs


대략 이러한 ItemDB라는 커스텀 클래스가 있다고 치자. (여기에 get/set 메소드를 더한)

Parcelable을 이용하기 위해 이를 implement하여 구현해야 한다.

이를 구현하고 나면 describeContents()와 writeToParcel(Parcel dest, int flags) 라는 메소드를 처리해야한다.

describeContents() 같은 경우에는 놔둬도 되고, 중요한 부분은 writeToParcel 부분이다.


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public class ItemDB implements Parcelable {    
    private final String TYPE_STRING = "string";
    private final String TYPE_DRAWABLE = "drawable";
    private int name;
    private int desc;
    private float hunger;
    private float armor;
    private float cooldown;
    private String attack;
    private String pc_ver;
    private String pe_ver;
    private String grid;
    private int icon;
    private Category category;
 
    public ItemDB(Parcel parcel) {
        // must be same order with writeToParcel()
        this.name = parcel.readInt();
        this.desc = parcel.readInt();
        this.icon = parcel.readInt();
        this.hunger = parcel.readFloat();
        this.armor = parcel.readFloat();
        this.cooldown = parcel.readFloat();
        this.attack = parcel.readString();
        this.pc_ver = parcel.readString();
        this.pe_ver = parcel.readString();
        this.grid = parcel.readString();
    }
 
    public ItemDB(...) {
        // your constructor
    }
 
    // create Parcelable
    public static final Parcelable.Creator<ItemDB> CREATOR = new Parcelable.Creator<ItemDB>() {
        @Override
        public ItemDB createFromParcel(Parcel parcel) {
            return new ItemDB(parcel);
        }
        @Override
        public ItemDB[] newArray(int size) {
            return new ItemDB[size];
        }
    };
 
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.name);
        dest.writeInt(this.desc);
        dest.writeInt(this.icon);
        dest.writeFloat(this.hunger);
        dest.writeFloat(this.armor);
        dest.writeFloat(this.cooldown);
        dest.writeString(this.attack);
        dest.writeString(this.pc_ver);
        dest.writeString(this.pe_ver);
        dest.writeString(this.grid);
    }
 
    @Override
    public int describeContents() {
        return 0;
    }
 
    public int getName {
        return this.name;
    }
}
cs


구현한 모습이다!.

35행은 Parcelable을 생성하는 코드다.

writeToParcel에서 Parcel 목적지(dest)에다가 데이터를 포맷에 따라 차곡차곡 넣어주고,

Parcel이 있는 생성자에서 순서대로 꺼내오면 된다. (두 개의 순서는 같아야 한다!)

이제 Parcel을 구현했으니 직접 Intent로 옮겨보자!


내 앱은 ItemListActivity에서 아이템을 클릭하면 ItemInfoActivity로 넘어가게 된다.

ItemListActivity.java

1
2
3
4
5
6
7
8
public class ItemListActivity extends Activity {    
    ...
    pubic void startActivityByItem(ItemDB item) {
        Intent intent = new Intent(this, ItemInfoActivity.class);
        intent.putExtra(ITEM_KEY, item);
        startActivity(intent);
    }
}
cs


String 으로 키 값을 주고, ItemDB 자체를 넘겨주는게 이제는 된다!

그러면 받는건 어떻게 하는지 보자.

ItemInfoActivity.java

1
2
3
4
5
6
public class ItemListActivity extends Activity {    
    ...
    ItemDB item = (ItemDB) getIntent().getParcelableExtra(ITEM_KEY);
    Log.e("[ITEM] 이름 :", getResources().getString(item.getName()));
}
 
cs


이런식으로 하면 Log에서는 클릭한 아이템 이름이 나오게 된다!



코코아 콩과 나침반을 누르니 정말 코코아 콩과 나침반이 찍힌다!

귀여워~