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

  1. parcelable Person;  

Pet.aidl

  1. parcelable Pet;   

可以看到,使用AIDL定义自定义类型只要一行代码

接下来我们来定义实现Parcelable接口的Persion类和Pet类

Person.java


  1. import android.os.Parcel;  
  2. import android.os.Parcelable;  
  3.   
  4. /** 
  5.  *  
  6.  * @author 大碗干拌 
  7.  * @url http://blog.csdn.net/dawanganban 
  8.  */  
  9. public class Person implements Parcelable  
  10. {  
  11.     private Integer id;  
  12.     private String name;  
  13.     private String pass;  
  14.   
  15.     public Person()  
  16.     {  
  17.     }  
  18.     public Person(Integer id, String name, String pass)  
  19.     {  
  20.         super();  
  21.         this.id = id;  
  22.         this.name = name;  
  23.         this.pass = pass;  
  24.     }  
  25.     public Integer getId()  
  26.     {  
  27.         return id;  
  28.     }  
  29.     public void setId(Integer id)  
  30.     {  
  31.         this.id = id;  
  32.     }  
  33.     public String getName()  
  34.     {  
  35.         return name;  
  36.     }  
  37.     public void setName(String name)  
  38.     {  
  39.         this.name = name;  
  40.     }  
  41.     public String getPass()  
  42.     {  
  43.         return pass;  
  44.     }  
  45.     public void setPass(String pass)  
  46.     {  
  47.         this.pass = pass;  
  48.     }  
  49.     @Override  
  50.     public int hashCode()  
  51.     {  
  52.         final int prime = 31;  
  53.         int result = 1;  
  54.         result = prime * result + ((name == null) ? 0 : name.hashCode());  
  55.         result = prime * result + ((pass == null) ? 0 : pass.hashCode());  
  56.         return result;  
  57.     }  
  58.     @Override  
  59.     public boolean equals(Object obj)  
  60.     {  
  61.         if (this == obj)  
  62.             return true;  
  63.         if (obj == null)  
  64.             return false;  
  65.         if (getClass() != obj.getClass())  
  66.             return false;  
  67.         Person other = (Person) obj;  
  68.         if (name == null)  
  69.         {  
  70.             if (other.name != null)  
  71.                 return false;  
  72.         }  
  73.         else if (!name.equals(other.name))  
  74.             return false;  
  75.         if (pass == null)  
  76.         {  
  77.             if (other.pass != null)  
  78.                 return false;  
  79.         }  
  80.         else if (!pass.equals(other.pass))  
  81.             return false;  
  82.         return true;  
  83.     }  
  84.     // 实现Parcelable接口必须实现的方法  
  85.     @Override  
  86.     public int describeContents()  
  87.     {  
  88.         return 0;  
  89.     }  
  90.     // 实现Parcelable接口必须实现的方法  
  91.     @Override  
  92.     public void writeToParcel(Parcel dest, int flags)  
  93.     {  
  94.         //把该对象所包含的数据写到Parcel  
  95.         dest.writeInt(id);  
  96.         dest.writeString(name);  
  97.         dest.writeString(pass);  
  98.     }  
  99.   
  100.     // 添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口  
  101.     public static final Parcelable.Creator<Person> CREATOR  
  102.         = new Parcelable.Creator<Person>() //①  
  103.     {  
  104.         @Override  
  105.         public Person createFromParcel(Parcel source)  
  106.         {  
  107.             // 从Parcel中读取数据,返回Person对象  
  108.             return new Person(source.readInt()  
  109.                 , source.readString()  
  110.                 , source.readString());  
  111.         }  
  112.   
  113.         @Override  
  114.         public Person[] newArray(int size)  
  115.         {  
  116.             return new Person[size];  
  117.         }  
  118.     };  
  119. }  

Pet.java


  1. import android.os.Parcel;  
  2. import android.os.Parcelable;  
  3.   
  4. /** 
  5.  *  
  6.  * @author 大碗干拌 
  7.  * @url http://blog.csdn.net/dawanganban 
  8.  */  
  9. public class Pet implements Parcelable  
  10. {  
  11.     private String name;  
  12.     private double weight;  
  13.     public Pet()  
  14.     {  
  15.     }  
  16.     public Pet(String name, double weight)  
  17.     {  
  18.         super();  
  19.         this.name = name;  
  20.         this.weight = weight;  
  21.     }  
  22.     public String getName()  
  23.     {  
  24.         return name;  
  25.     }  
  26.     public void setName(String name)  
  27.     {  
  28.         this.name = name;  
  29.     }  
  30.     public double getWeight()  
  31.     {  
  32.         return weight;  
  33.     }  
  34.     public void setWeight(double weight)  
  35.     {  
  36.         this.weight = weight;  
  37.     }  
  38.   
  39.     @Override  
  40.     public int describeContents()  
  41.     {  
  42.         return 0;  
  43.     }  
  44.     /* (non-Javadoc) 
  45.      * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int) 
  46.      */  
  47.     @Override  
  48.     public void writeToParcel(Parcel dest, int flags)  
  49.     {  
  50.         //把该对象所包含的数据写到Parcel  
  51.         dest.writeString(name);  
  52.         dest.writeDouble(weight);  
  53.     }  
  54.   
  55.     // 添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口  
  56.     public static final Parcelable.Creator<Pet> CREATOR  
  57.         = new Parcelable.Creator<Pet>()  
  58.     {  
  59.         @Override  
  60.         public Pet createFromParcel(Parcel source)  
  61.         {  
  62.             // 从Parcel中读取数据,返回Person对象  
  63.             return new Pet(source.readString()  
  64.                 , source.readDouble());  
  65.         }  
  66.   
  67.         @Override  
  68.         public Pet[] newArray(int size)  
  69.         {  
  70.             return new Pet[size];  
  71.         }  
  72.     };  
  73.     @Override  
  74.     public String toString()  
  75.     {  
  76.         return "Pet [name=" + name + ", weight=" + weight + "]";  
  77.     }  
  78. }  

上面代码定义了一个实现Parcelable接口的类,实现该接口主要就是要实现writeToParcel(Parel dest, int flags)方法,该方法负责把Person对象的数据写入Parcel中。与此同时,该类必须定义一个类型为Parcelable.Createor<Person>、名为CREATEOR的静态常亮,该静态常亮的值负责恢复从Parcel数据包中恢复Person对象,因此该对象定义的creaeFromPerson()方法用于恢复Person对象。

实际上Person类实现Parcelable接口也是一种序列化机制,只是Android没有直接使用Java提供的序列化机制,而是提供了Parcelable这种轻量级的序列化机制。

有了Person、Pet类后接下来就可以使用AIDL来定义通信接口了,定义通信接口的代码如下:

  1. interface IPet  
  2. {  
  3.     // 定义一个Person对象作为传入参数  
  4.     List<Pet> getPets(in Person owner);  
  5. }  

上面的in代表的是传入参数的方式是传参数

接下来开发一个Service类,让Service类的onBind方法返回IPet实现类的实例。代码如下:

  1. import java.util.ArrayList;  
  2. import java.util.HashMap;  
  3. import java.util.List;  
  4. import java.util.Map;  
  5.   
  6. import org.crazyit.service.IPet.Stub;  
  7.   
  8. import android.app.Service;  
  9. import android.content.Intent;  
  10. import android.os.IBinder;  
  11. import android.os.RemoteException;  
  12.   
  13. /** 
  14.  *  
  15.  * @author 大碗干拌 
  16.  * @url http://blog.csdn.net/dawanganban 
  17.  */  
  18. public class ComplexService extends Service  
  19. {  
  20.     private PetBinder petBinder;  
  21.     private static Map<Person , List<Pet>> pets  
  22.         = new HashMap<Person , List<Pet>>();  
  23.     static  
  24.     {  
  25.         // 初始化pets Map集合  
  26.         ArrayList<Pet> list1 = new ArrayList<Pet>();  
  27.         list1.add(new Pet("旺财" , 4.3));  
  28.         list1.add(new Pet("来福" , 5.1));  
  29.         pets.put(new Person(1"sun" , "sun") , list1);  
  30.         ArrayList<Pet> list2 = new ArrayList<Pet>();  
  31.         list2.add(new Pet("kitty" , 2.3));  
  32.         list2.add(new Pet("garfield" , 3.1));  
  33.         pets.put(new Person(2"bai" , "bai") , list2);  
  34.     }  
  35.     // 继承Stub,也就是实现额IPet接口,并实现了IBinder接口  
  36.     public class PetBinder extends Stub  
  37.     {  
  38.         @Override  
  39.         public List<Pet> getPets(Person owner) throws RemoteException  
  40.         {  
  41.             // 返回Service内部的数据  
  42.             return pets.get(owner);  
  43.         }  
  44.     }  
  45.     @Override  
  46.     public void onCreate()  
  47.     {  
  48.         super.onCreate();  
  49.         petBinder = new PetBinder();  
  50.     }  
  51.     @Override  
  52.     public IBinder onBind(Intent arg0)  
  53.     {  
  54.         /* 返回catBinder对象 
  55.          * 在绑定本地Service的情况下,该catBinder对象会直接 
  56.          * 传给客户端的ServiceConnection对象 
  57.          * 的onServiceConnected方法的第二个参数; 
  58.          * 在绑定远程Service的情况下,只将catBinder对象的代理 
  59.          * 传给客户端的ServiceConnection对象 
  60.          * 的onServiceConnected方法的第二个参数; 
  61.          */  
  62.         return petBinder; //①  
  63.     }  
  64.     @Override  
  65.     public void onDestroy()  
  66.     {  
  67.     }  
  68. }  

在AnroidMainfest.xml文件中配置Service,和前面的配置方法相同

下面我们来开发客户端

开发客户端的第一步不仅需要把IPet.aidl文件复制过去,还需要把定义Person类的Java文件,AIDL文件,定义Pet类的Java文件、AIDL文件也复制过去。

客户端代码如下:

  1. import java.util.List;  
  2.   
  3. import org.crazyit.service.IPet;  
  4. import org.crazyit.service.Person;  
  5. import org.crazyit.service.Pet;  
  6.   
  7. import android.app.Activity;  
  8. import android.app.Service;  
  9. import android.content.ComponentName;  
  10. import android.content.Intent;  
  11. import android.content.ServiceConnection;  
  12. import android.os.Bundle;  
  13. import android.os.IBinder;  
  14. import android.os.RemoteException;  
  15. import android.view.View;  
  16. import android.view.View.OnClickListener;  
  17. import android.widget.ArrayAdapter;  
  18. import android.widget.Button;  
  19. import android.widget.EditText;  
  20. import android.widget.ListView;  
  21.   
  22. /** 
  23.  *  
  24.  * @author 大碗干拌 
  25.  * @url http://blog.csdn.net/dawanganban 
  26.  * 
  27.  */  
  28. public class ComplexClient extends Activity  
  29. {  
  30.     private IPet petService;  
  31.     private Button get;  
  32.     EditText personView;  
  33.     ListView showView;  
  34.     private ServiceConnection conn = new ServiceConnection()  
  35.     {  
  36.         @Override  
  37.         public void onServiceConnected(ComponentName name  
  38.             , IBinder service)  
  39.         {  
  40.             // 获取远程Service的onBind方法返回的对象的代理  
  41.             petService = IPet.Stub.asInterface(service);  
  42.         }  
  43.   
  44.         @Override  
  45.         public void onServiceDisconnected(ComponentName name)  
  46.         {  
  47.             petService = null;  
  48.         }  
  49.     };  
  50.   
  51.     @Override  
  52.     public void onCreate(Bundle savedInstanceState)  
  53.     {  
  54.         super.onCreate(savedInstanceState);  
  55.         setContentView(R.layout.main);  
  56.         personView = (EditText) findViewById(R.id.person);  
  57.         showView = (ListView) findViewById(R.id.show);  
  58.         get = (Button) findViewById(R.id.get);  
  59.         // 创建所需绑定的Service的Intent  
  60.         Intent intent = new Intent();  
  61.         intent.setAction("org.crazyit.aidl.action.COMPLEX_SERVICE");  
  62.         // 绑定远程Service  
  63.         bindService(intent, conn, Service.BIND_AUTO_CREATE);  
  64.         get.setOnClickListener(new OnClickListener()  
  65.         {  
  66.             @Override  
  67.             public void onClick(View arg0)  
  68.             {  
  69.                 try  
  70.                 {  
  71.                     String personName = personView.getText().toString();  
  72.                     // 调用远程Service的方法  
  73.                     List<Pet> pets = petService.getPets(new Person(1,  
  74.                         personName, personName)); //①  
  75.                     // 将程序返回的List包装成ArrayAdapter  
  76.                     ArrayAdapter<Pet> adapter = new ArrayAdapter<Pet>(  
  77.                         ComplexClient.this,  
  78.                         android.R.layout.simple_list_item_1, pets);  
  79.                     showView.setAdapter(adapter);  
  80.                 }  
  81.                 catch (RemoteException e)  
  82.                 {  
  83.                     e.printStackTrace();  
  84.                 }  
  85.             }  
  86.         });  
  87.     }  
  88.   
  89.     @Override  
  90.     public void onDestroy()  
  91.     {  
  92.         super.onDestroy();  
  93.         // 解除绑定  
  94.         this.unbindService(conn);  
  95.     }  
  96. }  

0 0