今天犯二了, 犯了个超级低级的错误, 真的是丢人丢大发了.
刚好顺道反思下, 也对工作这几年做一些简单的总结. 不知道你们是不是和我一样也总遇到各种奇葩问题, 明明代码是对的可是就是不好使; 我明明声明了权限了但是就是获取不到; 这个bug以前没发生过啊, 我最近代码也没修改没道理出现问题啊, 肯定是其他地方的bug(尤其是多个人联合开发某个功能, 需要对接的时候)等等啦, 我以前遇到这个问题, 我的第一反应应该不是代码问题啊, 是不是哪里弄错了, 我"清楚的"记得代码写的没错, 是不是其他地方出问题导致的?. "事出反常必有妖啊", 而且往往证明最后的妖都出在我身上. 啥也不说了, 总结反思吧, 以后再出现这种问题,
第一, 先暗地里提醒自己是不是自己的问题, 不要上来就以为自己的代码没问题, 信誓旦旦找别人对问题, 结果发现最终还是自己的问题, 这脸打的太疼, 我有几次就是这样的
第二, 分析下出现问题的可能性, 找出对应的地方的代码
第三, 啥也别说, 仔细把出问题的那块的代码仔细看一遍, 我以前在网上看到过一个大神说的读书方法, 就一个字一个字的看, 我觉得说的对我很合适, 我发现我有段时间很浮躁, 读书看博客都是跳着看, 或者一目好几行, 这样是很快, 但是容易漏掉内容, 并且往往也领会不到深意, 我自认没有一目多行的能力, 以后还是老老实实一个字一个字看
第四, 一边过完, 再一个字一个字过一遍, 我觉得多看一遍不是浪费时间, 在仔细看过后 在去找相关的同事对问题, 这样能减少被打脸的几率么不是(/ □ \), 至少也要对自己写的代码负责么不是
检查问题一定要仔细, 耐心, 切忌一目多行, 草草了事
好了言归正传 Android AIDL使用, 我就是把我在使用AIDL时候遇到的问题和遇到的坑给总结一下, 供以后参考
AIDL(Android Interface Definition Language)即Android 接口定义语言, 主要是用于进程间通信, 方便进程间数据传递, 方法调用, 关于概念性的定义这里就不细讲了, 直接开始讲解使用方法, 关于注意事项, 我边讲边提吧
既然是进程间通信, 肯定要涉及service端和client端, 这里先说service端怎样对外提供服务
Service端
1.在Android Studio里创建AIDL文件夹
先说明一下service工程的包名: com.wb.aidl_service
工程跳到project模式下, 在工程的main上右键->New->Folder->AIDL Folder这样就创建了一个AIDL的专属目录如下图:
然后创建我们aidl文件夹下面的包: com.aidl.demo, 就是右键new->package
2.创建我们需要声明的aidl文件及响应的bean类的aidl文件
这里我的例子是"Android开发艺术探索"书里的基础上改的, 先说下Service里要用到的几个类:
Book.java Book对象的bean类, Book.aidl Book对象的aidl文件, IBookManager.aidl 对外提供方法的aidl文件, BookManagerService.java 服务端对外提供的service
第一个注意事项在进程间通讯的时候关于参数的传递问题: java的基本数据类型都支持, 对于自定义对象类型(例如上面说的Book对象)必须能够可序列化
众所周知Android里实现序列化的方法有两种implements Parcelable接口或者 implements Serializable接口这两个我们选择哪个呢? 当然是选择Parcelable接口了, 原因如下:
这里我直接引用别人的总结(李嘉欣-第四维空间 http://blog.csdn.net/ljx19900116/article/details/41699593 点击打开链接) : Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。
2.1创建实现了Parcelable接口的Book对象
public class Book implements Parcelable {
private String name;
private int price;
public Book() {
}
public Book(int price, String name) {
this.price = price;
this.name = name;
}
protected Book(Parcel in) {
name = in.readString();
price = in.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(price);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
这段代码没什么可说的, 就是定义两个属性, 然后实现set, get方法, 关于需要实现Parcelable的方法系统也会自动生成, 只需要注意一件事情就是包名: com.aidl.demo
2.2创建Book.java对应的Book.aidl文件
package com.aidl.demo;
// Declare any non-default types here with import statements
parcelable Book;
代码是不是超简洁, 总共就四行 , 还有两行是系统注释, 不过有个要注意的事项: 注意到包名了吗, 和上面创建的Book.java的包名是一样的
2.3创建IBookManager.aidl文件
// IBookManager.aidl
package com.aidl.demo;
// Declare any non-default types here with import statements
// 一定是全路径的类引用, 即使实在同一个包下
import com.aidl.demo.Book;
interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
}
这里代码也不多, 但是有个非常重要的地方需要注释, 也是困扰我了很久的一个知识点, 声明了一个interface, 里面两个方法, 一个是获取book列表, 一个是添加一本书