Android菜鸟的成长笔记(22)——Android进程间传递复杂数据(AIDL)
来源:互联网 发布:gamemaker mac 编辑:程序博客网 时间:2024/05/16 12:59
在上一篇中介绍了Andorid中的进程间的通信方式AIDL,本篇文章将介绍传递复杂数据的AIDL Service
下面通过一个示例说明:
本例子中用到了两个自定义类型:Person与Pet, 其中Person对象作为调用远程Service的参数,而Pet将作为返回值。就像RMI要求远程调用的参数和返回值必须实现Serializable接口,Android要求调用远程Service的参数和返回值都必须实现Parcelable接口。
实现Parcelable接口不仅要求实现该接口里定义的方法,还有两个要求:
1、要求在实现类中定义一个名为CREATOR、类型为Rarcelable.Creator的静态Field
2、要求使用AIDL代码来定义这些自定义类型。
实现Parcelable接口相当于Android提供的一种自定义序列化机制。Java序列化机制要求序列化类必须实现Serializable接口,而Android的序列化机制则要求自定义类必须实现Parcelable接口。
下面我们先来使用AIDL代码定义我们的自定义类型Person和Pet
Person.aidl
- parcelable Person;
Pet.aidl
- parcelable Pet;
可以看到,使用AIDL定义自定义类型只要一行代码
接下来我们来定义实现Parcelable接口的Persion类和Pet类
Person.java
- import android.os.Parcel;
- import android.os.Parcelable;
- /**
- *
- * @author 大碗干拌
- * @url http://blog.csdn.net/dawanganban
- */
- public class Person implements Parcelable
- {
- private Integer id;
- private String name;
- private String pass;
- public Person()
- {
- }
- public Person(Integer id, String name, String pass)
- {
- super();
- this.id = id;
- this.name = name;
- this.pass = pass;
- }
- public Integer getId()
- {
- return id;
- }
- public void setId(Integer id)
- {
- this.id = id;
- }
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- public String getPass()
- {
- return pass;
- }
- public void setPass(String pass)
- {
- this.pass = pass;
- }
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- result = prime * result + ((pass == null) ? 0 : pass.hashCode());
- return result;
- }
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Person other = (Person) obj;
- if (name == null)
- {
- if (other.name != null)
- return false;
- }
- else if (!name.equals(other.name))
- return false;
- if (pass == null)
- {
- if (other.pass != null)
- return false;
- }
- else if (!pass.equals(other.pass))
- return false;
- return true;
- }
- // 实现Parcelable接口必须实现的方法
- @Override
- public int describeContents()
- {
- return 0;
- }
- // 实现Parcelable接口必须实现的方法
- @Override
- public void writeToParcel(Parcel dest, int flags)
- {
- //把该对象所包含的数据写到Parcel
- dest.writeInt(id);
- dest.writeString(name);
- dest.writeString(pass);
- }
- // 添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口
- public static final Parcelable.Creator<Person> CREATOR
- = new Parcelable.Creator<Person>() //①
- {
- @Override
- public Person createFromParcel(Parcel source)
- {
- // 从Parcel中读取数据,返回Person对象
- return new Person(source.readInt()
- , source.readString()
- , source.readString());
- }
- @Override
- public Person[] newArray(int size)
- {
- return new Person[size];
- }
- };
- }
Pet.java
- import android.os.Parcel;
- import android.os.Parcelable;
- /**
- *
- * @author 大碗干拌
- * @url http://blog.csdn.net/dawanganban
- */
- public class Pet implements Parcelable
- {
- private String name;
- private double weight;
- public Pet()
- {
- }
- public Pet(String name, double weight)
- {
- super();
- this.name = name;
- this.weight = weight;
- }
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- public double getWeight()
- {
- return weight;
- }
- public void setWeight(double weight)
- {
- this.weight = weight;
- }
- @Override
- public int describeContents()
- {
- return 0;
- }
- /* (non-Javadoc)
- * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
- */
- @Override
- public void writeToParcel(Parcel dest, int flags)
- {
- //把该对象所包含的数据写到Parcel
- dest.writeString(name);
- dest.writeDouble(weight);
- }
- // 添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口
- public static final Parcelable.Creator<Pet> CREATOR
- = new Parcelable.Creator<Pet>()
- {
- @Override
- public Pet createFromParcel(Parcel source)
- {
- // 从Parcel中读取数据,返回Person对象
- return new Pet(source.readString()
- , source.readDouble());
- }
- @Override
- public Pet[] newArray(int size)
- {
- return new Pet[size];
- }
- };
- @Override
- public String toString()
- {
- return "Pet [name=" + name + ", weight=" + weight + "]";
- }
- }
上面代码定义了一个实现Parcelable接口的类,实现该接口主要就是要实现writeToParcel(Parel dest, int flags)方法,该方法负责把Person对象的数据写入Parcel中。与此同时,该类必须定义一个类型为Parcelable.Createor<Person>、名为CREATEOR的静态常亮,该静态常亮的值负责恢复从Parcel数据包中恢复Person对象,因此该对象定义的creaeFromPerson()方法用于恢复Person对象。
实际上Person类实现Parcelable接口也是一种序列化机制,只是Android没有直接使用Java提供的序列化机制,而是提供了Parcelable这种轻量级的序列化机制。
有了Person、Pet类后接下来就可以使用AIDL来定义通信接口了,定义通信接口的代码如下:
- interface IPet
- {
- // 定义一个Person对象作为传入参数
- List<Pet> getPets(in Person owner);
- }
上面的in代表的是传入参数的方式是传参数
接下来开发一个Service类,让Service类的onBind方法返回IPet实现类的实例。代码如下:
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.crazyit.service.IPet.Stub;
- import android.app.Service;
- import android.content.Intent;
- import android.os.IBinder;
- import android.os.RemoteException;
- /**
- *
- * @author 大碗干拌
- * @url http://blog.csdn.net/dawanganban
- */
- public class ComplexService extends Service
- {
- private PetBinder petBinder;
- private static Map<Person , List<Pet>> pets
- = new HashMap<Person , List<Pet>>();
- static
- {
- // 初始化pets Map集合
- ArrayList<Pet> list1 = new ArrayList<Pet>();
- list1.add(new Pet("旺财" , 4.3));
- list1.add(new Pet("来福" , 5.1));
- pets.put(new Person(1, "sun" , "sun") , list1);
- ArrayList<Pet> list2 = new ArrayList<Pet>();
- list2.add(new Pet("kitty" , 2.3));
- list2.add(new Pet("garfield" , 3.1));
- pets.put(new Person(2, "bai" , "bai") , list2);
- }
- // 继承Stub,也就是实现额IPet接口,并实现了IBinder接口
- public class PetBinder extends Stub
- {
- @Override
- public List<Pet> getPets(Person owner) throws RemoteException
- {
- // 返回Service内部的数据
- return pets.get(owner);
- }
- }
- @Override
- public void onCreate()
- {
- super.onCreate();
- petBinder = new PetBinder();
- }
- @Override
- public IBinder onBind(Intent arg0)
- {
- /* 返回catBinder对象
- * 在绑定本地Service的情况下,该catBinder对象会直接
- * 传给客户端的ServiceConnection对象
- * 的onServiceConnected方法的第二个参数;
- * 在绑定远程Service的情况下,只将catBinder对象的代理
- * 传给客户端的ServiceConnection对象
- * 的onServiceConnected方法的第二个参数;
- */
- return petBinder; //①
- }
- @Override
- public void onDestroy()
- {
- }
- }
在AnroidMainfest.xml文件中配置Service,和前面的配置方法相同
下面我们来开发客户端
开发客户端的第一步不仅需要把IPet.aidl文件复制过去,还需要把定义Person类的Java文件,AIDL文件,定义Pet类的Java文件、AIDL文件也复制过去。
客户端代码如下:
- import java.util.List;
- import org.crazyit.service.IPet;
- import org.crazyit.service.Person;
- import org.crazyit.service.Pet;
- import android.app.Activity;
- import android.app.Service;
- import android.content.ComponentName;
- import android.content.Intent;
- import android.content.ServiceConnection;
- import android.os.Bundle;
- import android.os.IBinder;
- import android.os.RemoteException;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.ArrayAdapter;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.ListView;
- /**
- *
- * @author 大碗干拌
- * @url http://blog.csdn.net/dawanganban
- *
- */
- public class ComplexClient extends Activity
- {
- private IPet petService;
- private Button get;
- EditText personView;
- ListView showView;
- private ServiceConnection conn = new ServiceConnection()
- {
- @Override
- public void onServiceConnected(ComponentName name
- , IBinder service)
- {
- // 获取远程Service的onBind方法返回的对象的代理
- petService = IPet.Stub.asInterface(service);
- }
- @Override
- public void onServiceDisconnected(ComponentName name)
- {
- petService = null;
- }
- };
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- personView = (EditText) findViewById(R.id.person);
- showView = (ListView) findViewById(R.id.show);
- get = (Button) findViewById(R.id.get);
- // 创建所需绑定的Service的Intent
- Intent intent = new Intent();
- intent.setAction("org.crazyit.aidl.action.COMPLEX_SERVICE");
- // 绑定远程Service
- bindService(intent, conn, Service.BIND_AUTO_CREATE);
- get.setOnClickListener(new OnClickListener()
- {
- @Override
- public void onClick(View arg0)
- {
- try
- {
- String personName = personView.getText().toString();
- // 调用远程Service的方法
- List<Pet> pets = petService.getPets(new Person(1,
- personName, personName)); //①
- // 将程序返回的List包装成ArrayAdapter
- ArrayAdapter<Pet> adapter = new ArrayAdapter<Pet>(
- ComplexClient.this,
- android.R.layout.simple_list_item_1, pets);
- showView.setAdapter(adapter);
- }
- catch (RemoteException e)
- {
- e.printStackTrace();
- }
- }
- });
- }
- @Override
- public void onDestroy()
- {
- super.onDestroy();
- // 解除绑定
- this.unbindService(conn);
- }
- }
- Android菜鸟的成长笔记(22)——Android进程间传递复杂数据(AIDL)
- Android菜鸟的成长笔记(22)——Android进程间传递复杂数据(AIDL)
- AIDL进程间传递复杂数据类型—AIDL传递android.os.Parcelable接口
- Android Service ---传递复杂数据的AIDL Service 笔记
- Android:使用AIDL实现进程间传递复杂数据类型
- android 怎样用AIDL Service 传递复杂数据
- Android使用AIDL时传递复杂数据对象的写法
- AIDL进程间传递复杂数据类型—AIDL传递其他AIDL接口
- Android基础--使用AIDL实现进程间的通信之复杂类型传递
- Android进程间通信(二)——传递复杂数据
- Android菜鸟的成长笔记(20)——IntentService
- Android菜鸟的成长笔记(20)——IntentService
- Android菜鸟在成长—ListView复杂列表信息项
- android -- 小功能 怎样用AIDL Service 传递复杂数据
- Android---45---使用AIDL Service传递复杂数据
- Android AIDL Service 跨进程传递复杂数据
- Android AIDL Service 跨进程传递复杂数据
- Android AIDL Service 跨进程传递复杂数据
- Android菜鸟的成长笔记(21)——跨进程调用Service
- Linux文件查看命令
- HTML 网页图标 页头图标
- sql数据库学习系列一之SQL Server 数据库设计
- Mongoose使用案例–让JSON数据直接入库MongoDB
- Android菜鸟的成长笔记(22)——Android进程间传递复杂数据(AIDL)
- uboot中用到的linux命令
- jquery
- 探索推荐引擎内部的秘密-第 2 部分: 深入推荐引擎相关算法 - 协同过滤
- linux备份mbr的方法
- Android菜鸟的成长笔记(23)——获取网络和SIM卡信息
- 吃蔬菜很可能让你患上皮炎
- 诚心找程序员合作
- Android菜鸟的成长笔记(24)——Android中的振动器