Android AIDL实现进程间通信

        今天犯二了, 犯了个超级低级的错误, 真的是丢人丢大发了大哭.

        刚好顺道反思下, 也对工作这几年做一些简单的总结. 不知道你们是不是和我一样也总遇到各种奇葩问题, 明明代码是对的可是就是不好使; 我明明声明了权限了但是就是获取不到; 这个bug以前没发生过啊, 我最近代码也没修改没道理出现问题啊, 肯定是其他地方的bug(尤其是多个人联合开发某个功能, 需要对接的时候)等等啦, 我以前遇到这个问题, 我的第一反应应该不是代码问题啊, 是不是哪里弄错了, 我"清楚的"记得代码写的没错, 是不是其他地方出问题导致的?.  "事出反常必有妖啊", 而且往往证明最后的妖都出在我身上尴尬. 啥也不说了, 总结反思吧, 以后再出现这种问题, 

        第一, 先暗地里提醒自己是不是自己的问题, 不要上来就以为自己的代码没问题, 信誓旦旦找别人对问题, 结果发现最终还是自己的问题, 这脸打的太疼大哭,  我有几次就是这样的

        第二, 分析下出现问题的可能性, 找出对应的地方的代码

        第三, 啥也别说, 仔细把出问题的那块的代码仔细看一遍, 我以前在网上看到过一个大神说的读书方法, 就一个字一个字的看, 我觉得说的对我很合适, 我发现我有段时间很浮躁, 读书看博客都是跳着看, 或者一目好几行, 这样是很快, 但是容易漏掉内容, 并且往往也领会不到深意, 我自认没有一目多行的能力,  以后还是老老实实一个字一个字看

        第四, 一边过完, 再一个字一个字过一遍, 我觉得多看一遍不是浪费时间, 在仔细看过后 在去找相关的同事对问题, 这样能减少被打脸的几率么不是(/ □ \), 至少也要对自己写的代码负责么不是

        检查问题一定要仔细, 耐心, 切忌一目多行, 草草了事

        好了言归正传 Android AIDL使用, 我就是把我在使用AIDL时候遇到的问题和遇到的坑给总结一下, 供以后参考

        AIDL(Android Interface Definition Language)即Android 接口定义语言, 主要是用于进程间通信, 方便进程间数据传递, 方法调用, 关于概念性的定义这里就不细讲了, 直接开始讲解使用方法, 关于注意事项, 我边讲边提吧

        既然是进程间通信, 肯定要涉及service端和client端, 这里先说service端怎样对外提供服务

AIDL的实现步骤:
    1.服务端
服务端首先要创建一个Service用来监听客户端的请求, 然后创建一个AIDL文件, 将暴露给客户端的接口在这个AIDL文件中声明, 最后在Service中实现这个AIDL接口即可

    2.客户端
客户端要做的事情就相对简单些, 首先绑定服务端的Service, 绑定成功后, 将服务端返回的Binder对象转成AIDL接口所属的类型, 接着就可以调用AIDL中的方法了

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对象

            这个创建对象不需要在aidl里, 就是在工程的src目录下即可
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文件

        为什么需要这个文件呢?  所有实现了Parcelable接口的并且要在AIDL接口中使用到的类都需要新建一个对应类名的.aidl文件., 文件内容就写 parcelable XXX
        在aidl文件夹下的包下右键->new->AIDL->AIDLfile
package com.aidl.demo;

// Declare any non-default types here with import statements

parcelable Book;

        代码是不是超简洁, 总共就四行 , 还有两行是系统注释偷笑, 不过有个要注意的事项: 注意到包名了吗, 和上面创建的Book.java的包名是一样的

        2.3创建IBookManager.aidl文件

           还是在aidl文件夹下的包下右键->new->AIDL->AIDL file
// 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列表, 一个是添加一本书
        这里注意第二个方法addBook(in Book book), 这里返回值是void没啥说的, 注意参数列表里的in(这个是表明跨进程间数据的流向共有in, out, inout三种), 这里重点说一下这个, 在对外提供的方法参数有以下几点要注意:
        1.基本类型不需要指明方向例如String, int等
        2. in 表现为服务端将会接收到一个那个对象的完整数据,但是客户端的那个对象不会因为服务端对传参的修改而发生变动;out 的话表现为服务端将会接收到那个对象的的空对象,但是在服务端对接收到的空对象有任何修改之后客户端将会同步变动;inout 为服务端将会接收到客户端传来对象的完整信息,并且客户端将会同步服务端对该对象的任何变动。(这个参考http://blog.csdn.net/luoyanglizi/article/details/51980630
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值