官方文档中介绍:

在Android上,一个进程通常无法访问另一个进程的内存,进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。我们可以通过AIDL来处理这个问题,我们必须使用到Parcelable接口。因为Android系统可以通过它将对象分解成可编组到各进程的原语。(也就是将对象转换成二进制代码,即序列化)

Parcelable

实现Parcelable就是为了序列化,Android中实现序列化有两个选择:一是实现Serializable接口(是JavaSE本身就支持的),一是实现Parcelable接口(是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC))。实现Serializable接口非常简单,声明一下就可以了,而实现Parcelable接口稍微复杂一些,但效率更高。

实现Serializable:

public class Person implements Serializable {
private String name;
private int id;
public Person(){}

}

实现Parcelable:
1)implements Parcelable
2)重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从 Parcel容器获取数据
3)重写describeContents方法,内容接口描述,默认返回0就可以
4)实例化静态内部对象CREATOR实现接口Parcelable.Creator
public static final Parcelable.Creator CREATOR

以上都是必须实现的

public class Person implements Parcelable {
private String name;
private int id;
public Person(){}

protected Person(Parcel in) {
name = in.readString();
id = in.readInt();
}

public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}

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

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

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(id);
}
}

AIDL传递对象

首先在Java包下面创建一个Person对象,并实现Parcelable的接口。其实是将上面的内容具体化:

public class Person implements Parcelable {
private String name;
private int id;
public Person(){}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public static Creator<Person> getCREATOR() {
return CREATOR;
}

public Person(int id,String name) {
this.name = name;
this.id = id;
}

protected Person(Parcel in) {
name = in.readString();
id = in.readInt();
}

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

//从Parcel中取出对象
@Override
public Person createFromParcel(Parcel in) {
return new Person(in.readInt(),in.readString());
}

//对象数组
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};

//描述内容
@Override
public int describeContents() {
return 0;
}

//将对象写入Parcel
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(id);
}
}

我们在AIDL下面创建Person.aidl,由于前面创建了Person类,所以我在创建Perison.aidl时,不能创建。于是我先创建为IPerson.aidl,然后改名为Person。

// Person.aidl
package com.example.aidldemo;
parcelable Person;

接下来创建一个IGetPerson的AIDL,实现获取Peron的方法,这里要注意,我们的Person需要导包,由于前面我们创建了Person.aidl,所以能够使用import将Person包导入进来。前面提到过,我们通过客户端输入,所以参数使用了in。
还需注意的是,每次创建完AIDL,都需要运行下,才能让Android系统为我们创建相应的java接口。

package com.example.aidldemo;
import com.example.aidldemo.Person;

interface IGetPerson {
List<Person> getPerson(in Person p);//参数中使用in
}

创建Service,并在Manifest中注册:

public class PersonService extends Service {
List<Person> persons = new ArrayList<>();

public PersonService() {
}

@Override
public IBinder onBind(Intent intent) {
return mbinder;//返回mbinder
}


private final IGetPerson.Stub mbinder = new IGetPerson.Stub() {
@Override
public List<Person> getPerson(Person p) throws RemoteException {
persons.add(p);//将Person加入到链表中
return persons;
}
};
}

在客户端的主要代码为:

  //点击事件
public void startService(View view) {
try {
Person person = new Person(1,"Jack");

list = iGetPerson.getPerson(person);//调用AIDl中的方法
//输出内容
StringBuilder builder = new StringBuilder();
for (Person p : list) {
builder.append(p.getId()).append(p.getName()).append(",");
}
textView.setText(builder);


} catch (RemoteException e) {
e.printStackTrace();
}
}

效果如图:

全部代码:

package com.example.aidldemo;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import java.util.List;

public class MainActivity extends AppCompatActivity {
private TextView textView ;
private IGetPerson iGetPerson;
private List<Person> list;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.text);

Intent intent = new Intent(MainActivity.this, PersonService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);

}

ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iGetPerson = IGetPerson.Stub.asInterface(service);

}

@Override
public void onServiceDisconnected(ComponentName name) {
iGetPerson = null;
}
};

public void startService(View view) {
try {
Person person = new Person(1,"Jack");

list = iGetPerson.getPerson(person);//调用AIDl中的方法
//输出内容
StringBuilder builder = new StringBuilder();
for (Person p : list) {
builder.append(p.getId()).append(p.getName()).append(",");
}
textView.setText(builder);


} catch (RemoteException e) {
e.printStackTrace();
}
}
}

布局代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.aidldemo.MainActivity">


<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="startService"
/>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/text"
/>


</LinearLayout>

这些都是我对AIDL的理解。

更多相关文章

  1. Android调用百度地图Web端接口,实现百度定位、导航
  2. 避免在Java接口中使用数组的3个理由
  3. 【Java笔记】——抽象类和接口
  4. GenericObjectPool对象池异常排查
  5. C#/Java 调用WSDL接口及方法
  6. Java对象创建的过程及对象的内存布局与访问定位
  7. request对象和response对象
  8. 20162305 实验二 Java面向对象程序设计 实验报告
  9. Java类的加载和对象创建流程的详细分析

随机推荐

  1. ImageView的src和background一些我的理解
  2. EditText实现输入限制和校验功能实例代码
  3. Android 设定横竖屏,屏幕旋转导致Activity
  4. android 线程(一)
  5. Android(安卓)HandlerThread全面解析
  6. Android之Intent全面解析及用法
  7. android国际化
  8. Android 之类库常用包
  9. 6、Android中的NFC技术
  10. android实现动画效果的方法onDrawFrame