Android进程间通信(二)——传递复杂数据

转载请指明出处: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的车辆信息,实现了复杂数据的跨进程传输。
这里写图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值