AIDL与service

时间:2024-12-04 00:03:32

Service:Local service,一个进程中的多线程服务。

AIDL:remote service,不同进程间通信。

Service启动方法:

startService():调用方destroy了那么服务不会销毁,不能与调用方直接适用,不返回任何结果。

bindService():调用方destroy了那么服务也会销毁,能与调用方直接通信。返回Binder。

* bindService时可以传递Binder的形式与调用方直接通信。在调用方需override叫ServiceConnnection的类来与service直接通信。

绑定成功后通过getService()获取Service对象,将Service对象设置为null,表示绑定意外失效,Service实例不再可用。

可以参考一下log:

操作步骤先用startService启动服务,然后destroy。

然后bindService绑定服务,然后destroy的结果如下:

AIDL与service

不难看出start方式启动服务时调用方销毁后服务不会自动stop。

而bind方式绑定服务时调用方销毁后服务自动解除绑定同时销毁。

生命周期相关:

AIDL与service

AIDL与service的区别

你可以试一试创建两个包不用AIDL的情况。

AIDL与service

通过ThreadRandomServiceDemo包中的ThreadRandomServiceDemo类去开启Demo中的RandomService是可以启动的但是无法获取,

有人会说利用bindService()不是利用可以ServiceConnection类返回Binder对象吗?是的,但是你无法加载Demo包(imorpt com.example.demo.RandomService)这样就我们无法与service直接数据交互通信了。

但是我们利用AIDL就可以调用其他进程(或其他project)直接通信。

AIDL是通过MyAidl.Stub.asInterface(binder);来获取binder的。

AIDL是以获取其他进程的接口来实现IPC通信的。

使用AIDL相关可以参考之前讲过的http://www.cnblogs.com/hongguang-kim/p/5165523.html

简单说明一下AIDL问价自动生成的java文件中我们可以看到Parcel。

Parcel是Android系统中应用程序进程间数据传递的容器,能够在两个进程中完成数据的打包和拆包的工作,

但Parcel不同于通用意义上的序列化,Parcel的设计目的是用于高性能IPC传输,因此不能够将Parcel对象保存在任何持久存储设备上。

当数据以Parcel对象的形式传递到跨进程服务的内部时,onTransact()方法将从Parcel对象中逐一的读取每个参数,然后调用Service内部制定的方法,

并再将结果写入另一个Parcel对象,准备将这个Parcel对象返回给远程的调用者。

自定义Parcel:

首先建立AllResult.aidl文件,声明AllResult类

package edu.hrbeu.ParcelMathServiceDemo;
parcelable AllResult;

在第2行代码中使用parcelable声明自定义类,这样其他的AIDL文件就可以使用这个自定义的类

构造AllResult类。AllResult类除了基本的构造函数以外,还需要有以Parcel对象为输入的构造函数,并且需要重载打包函数writeToParcel()
AllResult.java文件的完整代码如下

package edu.hrbeu.ParcelMathServiceDemo;

import android.os.Parcel;
import android.os.Parcelable; public class AllResult implements Parcelable {
public long AddResult;
public long SubResult;
public long MulResult;
public double DivResult;
. public AllResult(long addRusult, long subResult, long mulResult, double divResult){
AddResult = addRusult;
SubResult = subResult;
MulResult = mulResult;
DivResult = divResult;
} public AllResult(Parcel parcel) {
AddResult = parcel.readLong();
SubResult = parcel.readLong();
MulResult = parcel.readLong();
DivResult = parcel.readDouble();
} @Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(AddResult);34.
dest.writeLong(SubResult);
dest.writeLong(MulResult);
dest.writeDouble(DivResult);
} public static final Parcelable.Creator<AllResult> CREATOR =
new Parcelable.Creator<AllResult>(){
public AllResult createFromParcel(Parcel parcel){
return new AllResult(parcel);
}
public AllResult[] newArray(int size){
return new AllResult[size];
}
};
}

AllResult类继承于Parcelable
支持通过Parcel对象实例化AllResult内容是构造函数的读取顺序。
writeToParcel()是“打包”函数,将AllResult类内部的数据,按照特定的顺序写入Parcel对象,写入的顺序必须与构造函数的读取顺序一致
静态公共字段Creator,用来使用Parcel对象构造AllResult对象。

我们可以在其他类中编写如下代码:

  long addRusult = a + b;
long subResult = a - b;
long mulResult = a * b;
double divResult = (double) a / (double)b;
AllResult allResult = new AllResult(addRusult, subResult, mulResult, divResult);

我们可以通过result.AddResult变量获取其运算结果。