0
votes

I need to implement parcelable in my custom class "ArtistInfo" with the following structure:

    public class ArtistInfo implements Parcelable {

    private String artist;

    // album name to list of ids of songs
    private HashMap> albumInfo;

    // song id to songInfo
    private SparseArray songsMap;

    protected ArtistInfo(Parcel in) {
        artist = in.readString();
    }

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

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

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public void addSongsInfoToAlbum(List songsInfo, String album) {
        if (albumInfo == null) {
            albumInfo = new HashMap();
        }

        if (songsMap == null) {
            songsMap = new SparseArray();
        }
        List songsIds = new ArrayList();
        for (SongInfo songInfo : songsInfo) {
            songsIds.add(songInfo.getId());
            songsMap.put(songInfo.getId(), songInfo);
        }
        List songsIdsForAlbum = getSongIdsForAlbum(album);
        songsIdsForAlbum.addAll(songsIds);
        albumInfo.put(album, songsIdsForAlbum);
    }

    private List getSongIdsForAlbum(String album) {
        if (albumInfo == null) {
            return new ArrayList();
        }

        List songsIds = albumInfo.get(album);
        return songsIds == null ? new ArrayList() : songsIds;
    }

    public HashMap> getAlbumInfo() {
        return albumInfo;
    }

    public SparseArray getSongsMap() {
        if (songsMap == null) {
            songsMap = new SparseArray();
        }
        return songsMap;
    }

    @Override
    public String toString() {
        return "ArtistInfo{" +
                "artist='" + artist + '\'' +
                ", albumInfo=" + albumInfo.toString() +
                ", songsMap=" + songsMap.toString() +
                '}';
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(artist);
    }
}

And following is the structure of the "SongInfo" class used in the above class:

public class SongInfo implements Parcelable {

    private Integer id;

    private String name;

    private String url;

    public SongInfo(Integer id, String name, String url) {
        this.id = id;
        this.name = name;
        this.url = url;
    }

    protected SongInfo(Parcel in) {
        if (in.readByte() == 0) {
            id = null;
        } else {
            id = in.readInt();
        }
        name = in.readString();
        url = in.readString();
    }

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

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

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        if (id == null) {
            dest.writeByte((byte) 0);
        } else {
            dest.writeByte((byte) 1);
            dest.writeInt(id);
        }
        dest.writeString(name);
        dest.writeString(url);
    }
}

Now as you can see there is no problem in implementing the Parcelable interface in the SongInfo class, but I am not able to understand how to read and write the albumInfo and songsMap variables in the Constructor and writeToParcel method respectively. Can someone please help me understand how should I go ahead with that. Thanks!

1

1 Answers

1
votes

The idea is iterate through each item in albumInfo and songsMap then add it into Parcelable.

Write to parcel.

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(artist);

    // Write album info
    dest.writeInt(albumInfo.size());
    for (Map.Entry<String, List<Integer>> item : albumInfo.entrySet()) {
        dest.writeString(item.getKey());
        dest.writeList(item.getValue());
    }

    // Write song map
    dest.writeInt(songsMap.size());
    for (int i = 0; i < songsMap.size(); i++) {
        int key = songsMap.keyAt(i);
        dest.writeInt(key);
        dest.writeParcelable(songsMap.get(key), flags);
    }
}

Read from parcel

protected ArtistInfo(Parcel in) {
    artist = in.readString();

    // Read album info
    albumInfo = new HashMap<>();
    int albumInfoSize = in.readInt();
    for (int i = 0; i < albumInfoSize; i++) {
        String key = in.readString();
        List<Integer> value = new ArrayList<>();
        in.readList(value, null);
        albumInfo.put(key, value);
    }

    // Read song map
    songsMap = new SparseArray<>();
    int songsMapSize = in.readInt();
    for (int i = 0; i < songsMapSize; i++) {
        int key = in.readInt();
        SongInfo value = in.readParcelable(SongInfo.class.getClassLoader());
        songsMap.put(key, value);
    }
}