这一部分资料很多,我一边看着艺术探索,一边看着博客也跟着来了一遍,但怎么都无法编译通过,各种各样的错误,找不到类,找不到字段,巴拉巴拉。我实在是很郁闷,这么一个小小的东西怎么搞了2个小时?!然后查了一串串资料后我终于成功了!看到编译通过那一刻我就决定写一篇文章把它记下来,再也不摔在这里!
1、创建对象并实现Parcelable,我们以Person类为例:
package com.example.servicetest;
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable {
String name;
int age;
int sex;
public Person(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
dest.writeInt(this.age);
dest.writeInt(this.sex);
}
//注意:这个方法需要手动实现,自动生成工具不会生成。且各字段读取顺序应该与writeToParcel一致
public void readFromParcel(Parcel source) {
name = source.readString();
age = source.readInt();
sex = source.readInt();
}
protected Person(Parcel in) {
this.name = in.readString();
this.age = in.readInt();
this.sex = in.readInt();
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel source) {
return new Person(source);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
}
Parcelable接口的方法实现可以使用AS自动生成,但不包括readFromParcel方法。readFromParcel需要我们手动实现,否则无法编译通过。另外,readFromParcel各字段的读取顺序需要与writeToParcel一致。
2、新建与自定义对象同名的aidl文件,Person.aidl
在这里需要做两件事,一是声明对象为parcelable类型,注意大小写;二是必须手动import Person类,哪怕它们在同一个包下:
// Person.aidl
package com.example.servicetest;
//必须手动import
import com.example.servicetest.Person;
//parcelable首字母小写
parcelable Person;
这里踩坑了,如果在Java目录下新建了Person.java类,再新建Person.aidl类会发现失败了,AS告诉你它们同名了:
解决办法是先新建aidl文件,再新建Java文件。
或者新建Java文件的时候把它创建在aidl目录下,像这样:等aidl文件也创建成功后,可以把Java文件再挪出去到Java目录下就没问题了,我晕...
3、在AIDL接口文件内同样import我们自定义的对象:
所有使用自定义对象的aidl文件都应该手动import它。
// PersonAIDL.aidl
package com.example.servicetest;
import com.example.servicetest.Person;
// Declare any non-default types here with import statements
interface PersonAIDL {
String getName();
//in out inout只可用于非基础类型,
void setNameIn(in Person name);
void setNameOut(out Person name);
void setNameInOut(inout Person name);
}
然后build一下,你会发现失败了,报错大致是,找不到这个自定义类。我已经疯了,查资料,没有问题,emmm...再查
然后!
4、最后一步,在build.gradle文件中添加如下代码
位置在android 标签内,这应该与aidl文件的结构相关,话说这么重要的一步操作那些高赞文章怎么都不说呢,非让人家掉进去一次,不过也记得格外清楚了,哎
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java', 'src/main/aidl']
resources.srcDirs = ['src/main/java', 'src/main/aidl']
aidl.srcDirs = ['src/main/aidl']
res.srcDirs = ['src/main/res']
assets.srcDirs = ['src/main/assets']
}
}
踩了无数坑之后,终于编译通过了!一个小小的自定义对象居然这么艰辛!所以学东西一定要动手,眼睛是看不出这么多坑的,而且要记录,不然还会掉进去,到时候再一波一波的搜索解决方案可是有点费事儿了。