AIDL详解2——复杂数据通信

来源:互联网 发布:js将对象添加到数组中 编辑:程序博客网 时间:2024/06/14 10:07

官方文档中介绍:

在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.aidlpackage 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的理解。

原创粉丝点击