转载请指明出处:http://blog.csdn.net/fxdaniel/article/details/44279869
上一篇文章中介绍了如何在Android不同进程间传递数据,但是传递的都是基本数据类型或者String类型,这些都是系统数据类型。如何传递自定义数据类型呢?
下面我们来举个栗子。假设我们有两个自定义的类,一个是Person类,一个是Car类。一个Person对象有一个属性:姓名(name);一个Car对象有两个属性:品牌(brand)和价格(price)。一个人可以有多辆车,在客户端输入一个人的名字,就可以从服务端获取这个人拥有的车的信息。因为Person和Car都是自定义类,通过这个例子就可以看看如何在进程间传递自定义类型的数据。
还是先看服务端。
一、自定义类,实现Parcelable接口。
传递自定义类型和传递系统类型最大的区别就在于要为自定义类型实现Parcelable接口。其他步骤就和传递系统类型差不多了。
Parcelable接口是Android提供的一种轻量级的序列化方法。要在不同的进程间传递自定义的数据类型,就需要实现了Parcelable接口。
定义Person类和Car类,分别实现Parcelable接口。
Person类的代码如下:
package com.example.aidlservice;
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable {
private String name;
public Person() {
}
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 要将Person对象作为HashMap的key,就必须重写equals方法和hashCode方法
@Override
public boolean equals(Object o) {
if(o==this)
return true;
if(o==null)
return false;
if(getClass()!=o.getClass())
return false;
Person other=(Person)o;
if(name==null)
{
if(other.name!=null)
{
return false;
}
else
return true;
}
else
{
if(other.name==null)
return false;
else
{
if(name.equals(other.name))
return true;
}
}
return false;
}
@Override
public int hashCode() {
final int prime=31;
int result=1;
result=prime*result+((name==null)?0:name.hashCode());
return result;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
}
public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person[] newArray(int size) {
return new Person[size];
}
@Override
public Person createFromParcel(Parcel source) {
Person p=new Person(source.readString());
return p;
}
};
}
Car类的代码如下:
package com.example.aidlservice;
import android.os.Parcel;
import android.os.Parcelable;
public class Car implements Parcelable {
private Integer price;
private String brand;
public Car() {
super();
}
public Car(Integer price, String brand) {
super();
this.price = price;
this.brand = brand;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeInt(price);
dest.writeString(brand);
}
public static final Parcelable.Creator<Car> CREATOR = new Creator<Car>() {
@Override
public Car[] newArray(int size) {
// TODO Auto-generated method stub
return new Car[size];
}
@Override
public Car createFromParcel(Parcel source) {
// TODO Auto-generated method stub
return new Car(source.readInt(), source.readString());
}
};
}
二、为每个自定义类创建对应的aidl文件
Java代码写好以后,要为每个自定义类创建一个对应的aidl文件。aidl文件内容很简单,类似于一个声明。
Person.aidl文件内容如下:
parcelable Person;
Car.aidl文件内容如下:
parcelable Car;
三、在aidl文件中定义一个供远程调用的接口
ICar.aidl文件内容如下:
package com.example.aidlservice;
import com.example.aidlservice.Car;
import com.example.aidlservice.Person;
interface ICar
{
List<Car> getCars(in Person owner);
}
四、创建远程Service
package com.example.aidlservice;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class AidlService extends Service {
private CarBinder carBinder;
private static Map<Person,List<Car>> cars=new HashMap<Person,List<Car>>();
public AidlService() {
}
// 初始化块,初始化一些数据
static
{
List<Car> list1=new ArrayList<Car>();
list1.add(new Car(80000, "现代"));
list1.add(new Car(130000, "起亚"));
cars.put(new Person("小张"),list1);
List<Car> list2=new ArrayList<Car>();
list2.add(new Car(200000, "奥迪"));
list2.add(new Car(400000, "宝马"));
cars.put(new Person("李总"),list2);
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("Service created...");
// 此处创建一个CarBinder 的实例
carBinder=new CarBinder();
}
// 客户端绑定到本Service的时候会调用此方法
// 通过此方法将Binder的实例返回给客户端
@Override
public IBinder onBind(Intent intent) {
return carBinder;
}
@Override
public void onDestroy() {
super.onDestroy();
}
// 此处定义一个com.example.aidlservice.ICar.Stub类的子类
// 该类的实例会返回给客户端,供客户端调用
public class CarBinder extends ICar.Stub
{
// 回调方法,返回一个Person的车辆
@Override
public List<Car> getCars(Person owner) throws RemoteException {
return cars.get(owner);
}
}
}
最后配置一下service,服务端就完成了。
客户端的编写就和上一篇文章差不多了。先将Person.java、Car.java、Person.aidl、Car.aidl、ICar.aidl一起拷贝到AidlClient项目的com.example.aidlservice包下。然后在com.example.aidlclient包下编写Activity。直接上代码了:
package com.example.aidlclient;
import java.util.List;
import com.example.aidlservice.Car;
import com.example.aidlservice.ICar;
import com.example.aidlservice.Person;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class AidlClient extends Activity {
private Button get;
private EditText name;
private ICar carService;
private LinearLayout linearLayout;
private ServiceConnection conn=new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
carService=null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
carService=ICar.Stub.asInterface(service);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
get=(Button)findViewById(R.id.btn_get);
name=(EditText)findViewById(R.id.et_person);
linearLayout=(LinearLayout)findViewById(R.id.ll_show);
linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
// 绑定Service
Intent service=new Intent();
service.setAction("com.example.aidlservice.action.AIDL_SERVICE");
bindService(service, conn, Service.BIND_AUTO_CREATE);
get.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 清除所有TextView
linearLayout.removeAllViews();
try {
List<Car> cars=carService.getCars(new Person(name.getText().toString()));
if(cars==null)
{
System.out.println("error! cars is null...");
return;
}
StringBuilder sb=new StringBuilder();
sb.append("Person:"+name.getText().toString()+"\n");
TextView tv1=new TextView(AidlClient.this);
tv1.setText(sb.toString());
linearLayout.addView(tv1);
for(Car car:cars)
{
TextView tv=new TextView(AidlClient.this);
tv.setText("car:"+car.getBrand()+" "+car.getPrice());
linearLayout.addView(tv);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
this.unbindService(conn);
}
}
最后再配置一下Activity。
分别运行AidlServer和AidlClient项目。在客户端界面输入名字就可以获取到该Person的车辆信息,实现了复杂数据的跨进程传输。