android开发——跨进程通讯数据传递(二)

上一篇我们最后说到aidl,假定读到这篇的观众老爷们已经知道aidl是什么鬼了

不知道的自己查阅下资料,就会知道最基本的模型如下

在进程A中实现一个AIDL接口文件,进程B中也引用这个接口文件

// ITestService.aidl
package me.lzq.test;

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

interface ITestService {
    int sum(int a,int b);
}

该函数实现一个简单的加法功能


进程B中有一个服务叫做TestService,当A中的TestActivity启动TestService时,不使用startService,而是bindService

并且注册一个ServiceConnect对象,用来监听服务连接状况

public class TestActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent service = new Intent(this, TestService.class);
        bindService(service, conn, Service.BIND_AUTO_CREATE);
    }

    private ITestService binder;

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            binder = ITestService.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
}

在TestService中,实现ITestService中的sum方法,并在onBind中返回该接口对象
public class TestService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    private ITestService.Stub binder = new ITestService.Stub(){
        @Override
        public int sum(int a, int b) throws RemoteException {
            return a+b;
        }
    };
}

好了,以上就是最基本的aidl模型,已经熟悉的观众老爷们就当是一次复习吧

接下来才是我们本片文章的整体,数据传递部分

正如上面函数所示,我们传递的是基本数据类型int,那么如果我们要传递一个自定义类怎么办?

好吧,其实也是上文提到的Parcelable接口,不过有一点不同的是,我们需要在aidl中也声明这个类,如下

// A.aidl
package me.lzq.test;

// Declare any non-default types here with import statements
parcelable A;

注意这个aidl必须和java中的类A在一个package中,并且是同名

然后修改之前的ITestService.aidl,添加一个函数

interface ITestService {
    int sum(int a,int b);

    A modify(in A a);
}
输入一个类A的对象,并且返回一个类A,这样一来我们自定义的类也可以通过AIDL传递了

但是好像有些不完美的地方,是忘了什么吧?


对,为什么aidl中modify方法需要有一个in的关键字申明呢?在aidl中,自定义类有三种使用方式

in:顾名思义是输入,需要在客户端设置

out:输入,需要在服务器端设置

inout:两端均可设置

如果要使得你传入的自定义类可修改(相当于我们java中的对象引用),直接在类A中实现readFromParcel方法即可,完整的类A文件如下

public class A implements Parcelable {

    int a;
    long b;
    String c;

    public A(int a, long b, String c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    public A(Parcel source) {
        a = source.readInt();
        b = source.readLong();
        c = source.readString();
    }

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

    public void readFromParcel(Parcel source) {
        a = source.readInt();
        b = source.readLong();
        c = source.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(a);
        dest.writeLong(b);
        dest.writeString(c);
    }

    public final static Creator<A> CREATOR = new Creator<A>() {

        @Override
        public A createFromParcel(Parcel source) {
            return new A(source);
        }

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

这样一来,我们的自定义类就可以像之前在java中那样自由使用了

这样看来,似乎我们问题就都解决,但是还是有不完美的地方啊

因为我们每次使用一个自定义类就得去声明一个对应类型的aidl文件

这和我们实际开发不一样不一样啊!!!我们经常会对A进行继承

当在java中,我们可以通过多态来在一个函数中解决问题,可是aidl不是java啊!难道每次要传递一个继承的类,就需要声明一个aidl文件,并且在ITestService中声明一个新函数么?那么这也太不友好了,这不符合oo思想,对设计模式也会有极大的破坏


ok,问题还是好解决的,下一篇文章就会说明,如何使一个aidl传递的类,可以继承!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值