Activity 与 Service 实现Parcelable接口传递 ArrayList 集合

来源:互联网 发布:北京云计算公司排名 编辑:程序博客网 时间:2024/06/06 19:13

在 Activity 跟 Service 的通信过程中,一般用来传递数据的载体就是Intent了,一般用来传数据呢,我们都是通过putExtra 函数来传递简单的String,int, long类型的值,

但是现在存在这样一个问题:

1)在Activity里面有一个歌曲列表 List, 里面的对象是自定义的一个MusicInfo类,即 List<MusicInfo> 对象,这是用来展现的。

2)在后台Service中,也需要这样一个List<MusicInfo>, 来实现当歌曲播放结束的时候,自动循环播放或者顺序播放,或者随机播放。

我想要把整个List<MusicInfo> 给传过去,那该怎么办?

一般来说,将自定义的对象放到 Intent 里面来传递,可以有两种实现方法:

1)传递的对象实现 Serializable 接口,代码如下:

class MusicInfo implements Serializable{private static final long serialVersionUID = -39201440269615431L;...}
在设置 Intent 的时候,

intent.putExtra("music", new MusicInfo());

在Service 端接收 Intent 的时候,

intent.getSerializableExtra("music");

2)传递的对象实现Parcelable 接口,代码如下:

static class MusicInfo implements Parcelable{private static final long serialVersionUID = -39201440269615431L;...@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeLong(id);dest.writeString(title);dest.writeString(album);dest.writeString(artist);dest.writeString(url);dest.writeLong(duration);dest.writeLong(size);}public static final Parcelable.Creator<MusicInfo> CREATOR = new Creator<MusicLoader.MusicInfo>() {@Overridepublic MusicInfo[] newArray(int size) {// TODO Auto-generated method stubreturn new MusicInfo[size];}@Overridepublic MusicInfo createFromParcel(Parcel source) {// TODO Auto-generated method stubMusicInfo musicInfo = new MusicInfo();musicInfo.setId(source.readLong());musicInfo.setTitle(source.readString());musicInfo.setAlbum(source.readString());musicInfo.setArtist(source.readString());musicInfo.setUrl(source.readString());musicInfo.setDuration(source.readLong());musicInfo.setSize(source.readLong());return musicInfo;}};
其中下面三个方法是实现Parcelable 接口必须实现的:

1)describeContent () :  请参考:http://stackoverflow.com/questions/4076946/parcelable-where-when-is-describecontents-used

2)writeToParcel :将 MusicInfo 类中的值写放到一个Parcel容器中,这就是用来传递值的了

3)public static final Parcelable.Creator<T> CREATOR = new Creator<T>() :这是一个静态的接口,而且其名字一定要是CREATOR (=_=!!), 里面提供了两个方法,

3.1)public T[] newArray(int size) {} :返回一个 T 类型的数组

3.2)public T createFromParcel(Parcel source) {} : 从Parcel 中获取之前写入的数据,并封装成Parcel

对于这个Creator的接口,我的理解是,当我们把数据包装到Parcel中之后,它会被包装成一个 T 类型的数组(Music[] parcel),然后传递给Service或者其它Activity的时候,当系统要将Parcel中数据重新解析成我们自定义的对象的时候,它需要去调用Creator这个接口,先根据传入对象的长度 new 出一个T数组, 然后再CreateFromParcel,将内容转化成一个一个的 T 类型对象,放到数组中,返回给接收者。

可能也正是因为封装数组这种特性,当我们要在Android中传递开篇中提到的 List<MusicInfo> 集合的时候,只能实现Parcelable接口,用Serializable 是实现不了的。

另外有一点要注意的是,我们从Parcel 解析自定义的对象的时候,顺序必须跟我们写进去的顺序一致。

传送跟接收自定义的List<MusicInfo> 的代码如下:

intent.putParcelableArrayListExtra(NatureService.MUSICS, (ArrayList<? extends Parcelable>) musicList);
musicList = intent.getParcelableArrayListExtra(MUSICS);

我也尝试过让MusicInfo 去实现Serializable 接口,然后放到Intent 中来传送,但是没办法实现,会爆出以下的Exception.


看 Log,其还是用parcelable 接口去解析的。

P.S. 我的MusicInfo是一个子类,所以必须是静态子类,否则定义public, static 的 CREATOR 接口中时,是会错误的。




0 0
原创粉丝点击